【涂鸦T2-U】2、添加光感bh1750

news2024/11/20 10:40:30

文章目录

  • 前言
  • 一、基础介绍
  • 二、电路图
    • 2.1 电路图1
    • 2.2 电路图2——实际采用
  • 三、代码
  • 四、编译
  • 五、刷机
  • 六、测试结果
  • 小结

前言

本章介绍如何在涂鸦T2-U开发板上添加光感bh1750驱动并实现定时读取数据。

一、基础介绍

BH1750( GY-302 )光照传感器

这篇文章有bh1750的基础介绍。

我这里总结一下。

bh1750采用i2c通信,有5个引脚,vcc,gnd,sda,scl,add。
其中add接gnd时i2c地址为0x23,接vcc为0x5c。

模式:
三种分辨率模式,H(1lx),H2(0.5lx),L(41lx),其中1lx表示返回的数值1表示1lx,用于计算实际lx。
两种测试:连续,一次。
总共组合就是6中,常用的是一次H分辨率模式。

指令:
以一次H分辨率模式为例。

  1. 软重置:__bh1750_write_cmd(dev, BH1750_CMD_SOFT_RESET);
  2. 设置模式:__bh1750_write_cmd(dev, BH1750_CMD_ONE_H_RES_MODE);
  3. 等待采样:__bh1750_delay_ms(180);
  4. 读取采样值:__bh1750_read_data(dev, 2, buf);

如上述四步就可以读取到光感数据,剩下的就是实现接口和数据处理。
在这里插入图片描述

二、电路图

2.1 电路图1

一开始我打算使用默认的pin28和pin29作为sda和scl,但是不知道是不是和打开了串口调试开关有关,i2c通信失败,后续采用了20,22。

注意,虽然图上标的是p1和p0,但是对应的pin应该是28,29。
在这里插入图片描述

在这里插入图片描述

2.2 电路图2——实际采用

在这里插入图片描述

三、代码

代码基于tuyaos_sensor_hub_demo_quickstart实现的。
需要复制该项目,并仿照温感sht30的驱动,添加bh1750驱动。

tdd_sensor_light.h

/**
 * @file tdd_sensor_light.h
 * @brief tdd_sensor_light module is used to drive light & humidity sensor
 * @version 0.1
 * @date 2022-08-03
 */

#ifndef __TDD_SENSOR_LIGHT_H__
#define __TDD_SENSOR_LIGHT_H__

#include "tdl_sensor_type.h"
#include "tdd_sensor_i2c.h"

#ifdef __cplusplus
extern "C" {
#endif

/***********************************************************
************************macro define************************
***********************************************************/
/**
 * @brief element list
 */
#define SR_LT_ELE_ID_LIGHT           0x00
#define SR_LT_ELE_NUM               0x01

/**
 * @brief command list
 */
#define SR_LT_CMD_SOFT_RESET        0x00    // soft reset, param: none
#define SR_LT_CMD_GET_SERIAL_NBR    0x01    // read serial number, param: SR_LT_CMD_READ_SERIAL_NBR
#define SR_LT_CMD_SET_PREC          0x02    // set measurement precision, param: SR_LT_PREC_E
#define SR_LT_CMD_SET_FREQ          0x03    // set measurement frequency, param: SR_LT_FREQ_E
#define SR_LT_CMD_SET_ALT_LIMIT     0x04    // set alert thresholds, param: SR_LT_LIMIT_T
#define SR_LT_CMD_GET_ALT_LIMIT     0x05    // get alert thresholds, param: SR_LT_LIMIT_T
#define SR_LT_CMD_ENABLE_ALT_PIN    0x06    // enable alert pin, param: SR_LT_ALT_PIN_T
#define SR_LT_CMD_DISABLE_ALT_PIN   0x07    // disable alert pin, param: TKL_GPIO_NAME_E
#define SR_LT_CMD_GET_STATUS        0x08    // read status register, param: SR_LT_STATUS_U
#define SR_LT_CMD_CLR_STATUS        0x09    // clear status register, param: none
#define SR_LT_CMD_ENABLE_HEATER     0x0A    // enable heater, param: none
#define SR_LT_CMD_DISABLE_HEATER    0x0B    // disable heater, param: none
#define SR_LT_CMD_ACTIVATE_HEATER   0x0C    // activate heater for a while, param: SR_LT_HEATER_T

/**
 * @brief I2C address list
 */
#define SR_I2C_ADDR_BH1750_A         0x23    // BH1750 : ADDR pin - GND
#define SR_I2C_ADDR_BH1750_B         0x5c    // BH1750 : ADDR pin - VCC
// #define SR_I2C_ADDR_SHT4X_A         0x44    // SHT4x-A */
// #define SR_I2C_ADDR_SHT4X_B         0x45    // SHT4x-B */
// #define SR_I2C_ADDR_CHT8305_A       0x40    // CHT8305 : AD0 pin - GND
// #define SR_I2C_ADDR_CHT8305_B       0x44    // CHT8305 : AD0 pin - VCC
// #define SR_I2C_ADDR_CHT8305_C       0x48    // CHT8305 : AD0 pin - SDA
// #define SR_I2C_ADDR_CHT8305_D       0x4C    // CHT8305 : AD0 pin - SCL


/***********************************************************
***********************typedef define***********************
***********************************************************/
/**
 * @brief measurement precision
 *        enum value for SR_LT_CMD_SET_PREC
 */
typedef BYTE_T SR_LT_PREC_E;
#define SR_LT_PREC_HIGH             0x00
#define SR_LT_PREC_MEDIUM           0x01
#define SR_LT_PREC_LOW              0x02
#define SR_LT_PREC_INVALID          0x03

/**
 * @brief measurement frequency
 *        enum value for SR_LT_CMD_SET_FREQ
 */
typedef BYTE_T SR_LT_FREQ_E;
#define SR_LT_FREQ_ONE              0x00
#define SR_LT_FREQ_CON              0x01
#define SR_LT_FREQ_INVALID          0x02

/**
 * @brief heater work power
 *        enum value for SR_LT_CMD_ACTIVATE_HEATER
 */
typedef BYTE_T SR_LT_HEATER_PWR_E;
#define SR_LT_HEATER_PWR_HIGH       0x00
#define SR_LT_HEATER_PWR_MEDIUM     0x01
#define SR_LT_HEATER_PWR_LOW        0x02
#define SR_LT_HEATER_PWR_INVALID    0x03

/**
 * @brief heater work time
 *        enum value for SR_LT_CMD_ACTIVATE_HEATER
 */
typedef BYTE_T SR_LT_HEATER_TIM_E;
#define SR_LT_HEATER_TIM_LONG       0x00
#define SR_LT_HEATER_TIM_SHORT      0x01
#define SR_LT_HEATER_TIM_INVALID    0x02

/**
 * @brief I2C configuration
 */
typedef struct {
    UCHAR_T         port;
    UCHAR_T         addr;
    SR_I2C_GPIO_T   gpio;
} SR_LT_I2C_CFG_T;

/**
 * @brief measurement configuration
 *        param type for tdd_sensor_bh1750_register
 */
typedef struct {
    SR_LT_PREC_E prec;
    SR_LT_FREQ_E freq;
} SR_LT_MEAS_CFG_T;

/**
 * @brief alert limit
 *        param type for SR_LT_CMD_SET_ALT_LIMIT
 *                   and SR_LT_CMD_GET_ALT_LIMIT
 *        light_range: -40 ~ 125 (°C)
 *        humi_range:   0 ~ 100 (%RH)
 */
typedef struct {
    SR_VAL_U light_high_set;
    SR_VAL_U light_high_clear;
    SR_VAL_U light_low_set;
    SR_VAL_U light_low_clear;
} SR_LT_LIMIT_T;

/**
 * @brief alert pin configuration
 *        param type for SR_LT_CMD_ENABLE_ALT_PIN
 */
typedef struct {
    TUYA_GPIO_NUM_E pin;
    TUYA_GPIO_IRQ_T irq;
} SR_LT_ALT_CFG_T;

/**
 * @brief heater configuration
 *        param type for SR_LT_CMD_ACTIVATE_HEATER
 */
typedef struct {
    SR_LT_HEATER_PWR_E power;
    SR_LT_HEATER_TIM_E time;
} SR_LT_HEATER_T;

/**
 * @brief status register value
 *        param type for SR_LT_CMD_GET_STATUS
 */
typedef union {
    // little-endian
    struct {
        USHORT_T crc_status     : 1;
        USHORT_T cmd_status     : 1;
        USHORT_T reserve0       : 2;
        USHORT_T reset_detected : 1;
        USHORT_T reserve1       : 5;
        USHORT_T light_alert     : 1;
        USHORT_T humi_alert     : 1;
        USHORT_T reserve2       : 1;
        USHORT_T heater_status  : 1;
        USHORT_T reserve3       : 1;
        USHORT_T alert_pending  : 1;
    } bit;
    // can use "word" directly
    USHORT_T word;
} SR_LT_STATUS_U;

/**
 * @brief serial number
 *        param type for SR_LT_CMD_READ_SERIAL_NBR
 */
typedef struct {
    UINT_T val;
} SR_LT_SERIAL_NBR_T;

/***********************************************************
********************function declaration********************
***********************************************************/
/**
 * @brief register bh1750 device
 *
 * @param[in] name: device name
 * @param[in] i2c_cfg: i2c configuration
 * @param[in] meas_cfg: measurement configuration
 *
 * @return OPRT_OK on success, others on error
 */
OPERATE_RET tdd_sensor_bh1750_register(IN CHAR_T *name, IN SR_LT_I2C_CFG_T i2c_cfg, IN SR_LT_MEAS_CFG_T meas_cfg);

#ifdef __cplusplus
}
#endif

#endif /* __TDD_SENSOR_LIGHT_H__ */

app_light.h

/**
 * @file app_light.h
 * @brief RH-T sensor application demo
 * @version 0.1
 * @date 2022-09-01
 */

#ifndef __APP_LIGHT_H__
#define __APP_LIGHT_H__

#include "tuya_cloud_com_defs.h"

#ifdef __cplusplus
extern "C" {
#endif

/***********************************************************
************************macro define************************
***********************************************************/
/*
 *@brief product id define
*/
#define PID "8q46zzdfuofastqr"

/**
 * @brief function define
 */
#define APP_LIGHT_READ_CYCLE            2  * 1000               // units:ms
#define APP_LIGHT_REPORT_CYCLE          10 * 1000               // units:ms

/**
 * @brief pin define
 */
#define BH1750_SCL_PIN   GPIO_NUM_20
#define BH1750_SDA_PIN   GPIO_NUM_22
#define BH1750_ALT_PIN   GPIO_NUM_14

/**
 * @brief DP list
 */
#define DP_ID_LIGHT      1

#define DP_ID_LIGHT_MAX  10
#define DP_ID_LIGHT_MIN  11

#define DP_ID_LIGHT_ALT  12

#define DP_ID_SWITCH    21

#define MAX_DP_NUM          9

/**
 * @brief Data scale
 */
#define LIGHT_SCALE      1           // raw-data * 10

/**
 *@brief report interval
 */
#define APP_LIGHT_REPORT_INTERVAL        20          // default: 2.0 ℃

/**
 *@brief kv key name
 */
#define KEY_NAME "light"

/***********************************************************
***********************typedef define***********************
***********************************************************/

/***********************************************************
********************function declaration********************
***********************************************************/
/**
 * @brief light main
 *
 * @param none
 *
 * @return OPRT_OK on success. Others on error, please refer to "tuya_error_code.h"
 */
OPERATE_RET app_light_init(VOID_T);

/**
 * @brief DP processing
 *
 * @param[in] dp: dp data
 *
 * @return none
 */
VOID_T app_light_dp_proc(CONST TY_OBJ_DP_S *dp);

/**
 * @brief report all DP data
 *
 * @param none
 *
 * @return none
 */
VOID_T app_light_repo_all_dp(VOID_T);

#ifdef __cplusplus
}
#endif

#endif /* __APP_LIGHT_H__ */

tdd_sensor_bh1750.c

/**
 * @file tdd_sensor_bh1750.c
 * @brief tdd_sensor_bh1750 module is used to drive bh1750 chip
 * @version 0.1
 * @date 2022-08-03
 */

#include "tdl_sensor_driver.h"
#include "tdd_sensor_light.h"
#include "tkl_gpio.h"
#include "tal_system.h"
#include "tal_log.h"

/***********************************************************
************************macro define************************
***********************************************************/
/**
 * @brief CRC result
 */
#define CRC_OK                      (0)
#define CRC_ERR                     (-1)

/**
 * @brief work status
 */
#define BH1750_CLOSE                 0
#define BH1750_OPEN                  (!BH1750_CLOSE)

/**
 * @brief resource array index
 */
#define BH1750_RSRC_INDEX_STAT       0
#define BH1750_RSRC_INDEX_ADDR       1
#define BH1750_RSRC_INDEX_PREC       2  // H-Resolution Mode/H-Resolution Mode2/L-Resolution
#define BH1750_RSRC_INDEX_FREQ       3  // one/continue
#define BH1750_RSRC_INDEX_RESL       4  // mode match value, such as H=1,H2=0.5,L=41

/***********************************************************
***********************typedef define***********************
***********************************************************/
/**
 * @brief bh1750 command
 */
typedef USHORT_T BH1750_CMD_E;


#define BH1750_CMD_POWER_DOWN   	    0x00	// power down
#define BH1750_CMD_POWER_ON			    0x01	// power on
#define BH1750_CMD_SOFT_RESET			0x07	// reset


#define BH1750_CMD_CON_H_RES_MODE	    0x10	// Continuously H-Resolution Mode
#define BH1750_CMD_CON_H_RES_MODE2	    0x11	// Continuously H-Resolution Mode2
#define BH1750_CMD_CON_L_RES_MODE	    0x13	// Continuously L-Resolution Mode
#define BH1750_CMD_ONE_H_RES_MODE	    0x20	// One Time H-Resolution Mode
#define BH1750_CMD_ONE_H_RES_MODE2	    0x21	// One Time H-Resolution Mode2
#define BH1750_CMD_ONE_L_RES_MODE	    0x23	// One Time L-Resolution Mode



// #define BH1750_CMD_SOFT_RESET        0x30A2  // soft reset
#define BH1750_CMD_READ_SERIALNBR    0x3780  // read serial number
#define BH1750_CMD_HEATER_ENABLE     0x306D  // enabled heater
#define BH1750_CMD_HEATER_DISABLE    0x3066  // disable heater
#define BH1750_CMD_READ_STATUS       0xF32D  // read status register
#define BH1750_CMD_CLEAR_STATUS      0x3041  // clear status register
#define BH1750_CMD_ART               0x2B32  // activate ART
#define BH1750_CMD_BREAK             0x3093  // stop periodic data acquisition mode
#define BH1750_CMD_FETCH_DATA        0xE000  // readout measurements for periodic mode
#define BH1750_CMD_MEAS_PERI_05_H    0x2032  // measurement: periodic 0.5 mps, high repeatability
#define BH1750_CMD_MEAS_PERI_05_M    0x2024  // measurement: periodic 0.5 mps, medium repeatability
#define BH1750_CMD_MEAS_PERI_05_L    0x202F  // measurement: periodic 0.5 mps, low repeatability
#define BH1750_CMD_MEAS_PERI_1_H     0x2130  // measurement: periodic 1 mps, high repeatability
#define BH1750_CMD_MEAS_PERI_1_M     0x2126  // measurement: periodic 1 mps, medium repeatability
#define BH1750_CMD_MEAS_PERI_1_L     0x212D  // measurement: periodic 1 mps, low repeatability
#define BH1750_CMD_MEAS_PERI_2_H     0x2236  // measurement: periodic 2 mps, high repeatability
#define BH1750_CMD_MEAS_PERI_2_M     0x2220  // measurement: periodic 2 mps, medium repeatability
#define BH1750_CMD_MEAS_PERI_2_L     0x222B  // measurement: periodic 2 mps, low repeatability
#define BH1750_CMD_MEAS_PERI_4_H     0x2334  // measurement: periodic 4 mps, high repeatability
#define BH1750_CMD_MEAS_PERI_4_M     0x2322  // measurement: periodic 4 mps, medium repeatability
#define BH1750_CMD_MEAS_PERI_4_L     0x2329  // measurement: periodic 4 mps, low repeatability
#define BH1750_CMD_MEAS_PERI_10_H    0x2737  // measurement: periodic 10 mps, high repeatability
#define BH1750_CMD_MEAS_PERI_10_M    0x2721  // measurement: periodic 10 mps, medium repeatability
#define BH1750_CMD_MEAS_PERI_10_L    0x272A  // measurement: periodic 10 mps, low repeatability
#define BH1750_CMD_MEAS_POLLING_H    0x2400  // measurement: polling, high repeatability
#define BH1750_CMD_MEAS_POLLING_M    0x240B  // measurement: polling, medium repeatability
#define BH1750_CMD_MEAS_POLLING_L    0x2416  // measurement: polling, low repeatability
#define BH1750_CMD_MEAS_CLOCKSTR_H   0x2C06  // measurement: clock stretching, high repeatability
#define BH1750_CMD_MEAS_CLOCKSTR_M   0x2C0D  // measurement: clock stretching, medium repeatability
#define BH1750_CMD_MEAS_CLOCKSTR_L   0x2C10  // measurement: clock stretching, low repeatability
#define BH1750_CMD_W_AL_LIM_HS       0x611D  // write alert limits, high set
#define BH1750_CMD_W_AL_LIM_HC       0x6116  // write alert limits, high clear
#define BH1750_CMD_W_AL_LIM_LC       0x610B  // write alert limits, low clear
#define BH1750_CMD_W_AL_LIM_LS       0x6100  // write alert limits, low set
#define BH1750_CMD_R_AL_LIM_LS       0xE102  // read alert limits, low set
#define BH1750_CMD_R_AL_LIM_LC       0xE109  // read alert limits, low clear
#define BH1750_CMD_R_AL_LIM_HS       0xE11F  // read alert limits, high set
#define BH1750_CMD_R_AL_LIM_HC       0xE114  // read alert limits, high clear

/***********************************************************
********************function declaration********************
***********************************************************/

/***********************************************************
***********************variable define**********************
***********************************************************/
/**
 * @brief element value type
 */
#if (SR_CONFIG_NO_FPU == 1)
STATIC SR_ELE_CFG_T sg_ele_val_tp[SR_LT_ELE_NUM] = {
    {
        .id     = SR_LT_ELE_ID_LIGHT,
        .val_tp = SR_VAL_TP_INT,
    }
};
#else
STATIC SR_ELE_CFG_T sg_ele_val_tp[SR_LT_ELE_NUM] = {
    {
        .id     = SR_LT_ELE_ID_LIGHT,
        .val_tp = SR_VAL_TP_FLOAT,
    }
};
#endif

/***********************************************************
***********************function define**********************
***********************************************************/
/**
 * @brief delay (ms)
 *
 * @param[in] tm: delay time
 *
 * @return none
 */
STATIC VOID_T __bh1750_delay_ms(IN CONST ULONG_T tm)
{
    tal_system_sleep(tm);
}

/**
 * @brief get CRC8 value for bh1750
 *
 * @param[in] data: data to be calculated
 * @param[in] len: data length
 *
 * @return CRC8 value
 */
STATIC UCHAR_T __bh1750_get_crc8(IN CONST UCHAR_T *data, IN USHORT_T len)
{
    UCHAR_T i;
    UCHAR_T crc = 0xFF;

    while (len--) {
        crc ^= *data;

        for (i = 8; i > 0; --i) {
            if (crc & 0x80) {
                crc = (crc << 1) ^ 0x31;
            } else {
                crc = (crc << 1);
            }
        }
        data++;
    }

    return crc;
}

/**
 * @brief check CRC8
 *
 * @param[in] data: data to be checked
 * @param[in] len: data length
 * @param[in] crc_val: crc value
 *
 * @return check result
 */
STATIC INT_T __bh1750_check_crc8(IN CONST UCHAR_T *data, IN CONST USHORT_T len, IN CONST UCHAR_T crc_val)
{
    if (__bh1750_get_crc8(data, len) != crc_val) {
        return CRC_ERR;
    }
    return CRC_OK;
}

/**
 * @brief read data from bh1750
 *
 * @param[in] dev: device resource
 * @param[in] len: data length
 * @param[out] data: data received from bh1750
 *
 * @return none
 */
STATIC OPERATE_RET __bh1750_read_data(IN CONST SR_RSRC_T *dev, IN CONST USHORT_T len, OUT UCHAR_T *data)
{
    SR_I2C_MSG_T rd_msg = {
        .flags = SR_I2C_FLAG_RD,
        .addr = dev->info[BH1750_RSRC_INDEX_ADDR],
        .len = len,
        .buff = data
    };

    return tdd_sensor_i2c_xfer(dev->port, &rd_msg);
}

/**
 * @brief write command to bh1750
 *
 * @param[in] dev: device resource
 * @param[in] cmd: control command
 *
 * @return none
 */
STATIC OPERATE_RET __bh1750_write_cmd2(IN CONST SR_RSRC_T *dev, IN CONST BH1750_CMD_E cmd)
{
    UCHAR_T cmd_bytes[2];
    cmd_bytes[0] = (UCHAR_T)(cmd >> 8);
    cmd_bytes[1] = (UCHAR_T)(cmd & 0x00FF);

    SR_I2C_MSG_T wr_msg = {
        .flags = SR_I2C_FLAG_WR,
        .addr = dev->info[BH1750_RSRC_INDEX_ADDR],
        .len = 2,
        .buff = cmd_bytes
    };

    return tdd_sensor_i2c_xfer(dev->port, &wr_msg);
}

STATIC OPERATE_RET __bh1750_write_cmd(IN CONST SR_RSRC_T *dev, IN CONST BH1750_CMD_E cmd)
{
    UCHAR_T cmd_bytes;
    cmd_bytes = (UCHAR_T)(cmd & 0xFF);

    SR_I2C_MSG_T wr_msg = {
        .flags = SR_I2C_FLAG_WR,
        .addr = dev->info[BH1750_RSRC_INDEX_ADDR],
        .len = 1,
        .buff = &cmd_bytes
    };

    // TAL_PR_ERR("[BH1750] addr=0x%02x, cmd=0x%02x",dev->info[BH1750_RSRC_INDEX_ADDR], cmd_bytes);

    return tdd_sensor_i2c_xfer(dev->port, &wr_msg);
}

/**
 * @brief write command and data to bh1750
 *
 * @param[in] dev: device resource
 * @param[in] cmd: control command
 * @param[in] data: data to be written
 *
 * @return none
 */
STATIC VOID_T __bh1750_write_2bytes_data(IN CONST SR_RSRC_T *dev, IN CONST BH1750_CMD_E cmd, IN CONST USHORT_T data)
{
    UCHAR_T buf[5];
    buf[0] = (UCHAR_T)(cmd >> 8);
    buf[1] = (UCHAR_T)(cmd & 0x00FF);
    buf[2] = (UCHAR_T)(data >> 8);
    buf[3] = (UCHAR_T)(data & 0x00FF);
    buf[4] = __bh1750_get_crc8(buf+2, 2);

    SR_I2C_MSG_T wr_msg = {
        .flags = SR_I2C_FLAG_WR,
        .addr = dev->info[BH1750_RSRC_INDEX_ADDR],
        .len = 5,
        .buff = buf
    };

    tdd_sensor_i2c_xfer(dev->port, &wr_msg);
}

/**
 * @brief start periodic measurement
 *
 * @param[in] dev: device resource
 *
 * @return none
 */
STATIC VOID_T __bh1750_start_periodic_measurement(IN CONST SR_RSRC_T *dev)
{
    switch (dev->info[BH1750_RSRC_INDEX_PREC]) {
    default:
    case SR_LT_PREC_HIGH:
        switch (dev->info[BH1750_RSRC_INDEX_FREQ]) {
            case SR_LT_FREQ_ONE:
                __bh1750_write_cmd(dev, BH1750_CMD_ONE_H_RES_MODE);
                break;
            case SR_LT_FREQ_CON:
                __bh1750_write_cmd(dev, BH1750_CMD_CON_H_RES_MODE);
                break;
        }
        break;

    case SR_LT_PREC_MEDIUM:
        switch (dev->info[BH1750_RSRC_INDEX_FREQ]) {
            case SR_LT_FREQ_ONE:
                __bh1750_write_cmd(dev, BH1750_CMD_ONE_H_RES_MODE);
                break;
            case SR_LT_FREQ_CON:
                __bh1750_write_cmd(dev, BH1750_CMD_CON_H_RES_MODE);
                break;
        }
        break;

    case SR_LT_PREC_LOW:
        switch (dev->info[BH1750_RSRC_INDEX_FREQ]) {
            case SR_LT_FREQ_ONE:
                __bh1750_write_cmd(dev, BH1750_CMD_ONE_L_RES_MODE);
                break;
            case SR_LT_FREQ_CON:
                __bh1750_write_cmd(dev, BH1750_CMD_CON_L_RES_MODE);
                break;
        }
        break;
    }
}

/**
 * @brief stop periodic measurement
 *
 * @param[in] dev: device resource
 *
 * @return none
 */
STATIC VOID_T __bh1750_stop_periodic_measurement(IN CONST SR_RSRC_T *dev)
{
    __bh1750_write_cmd(dev, BH1750_CMD_ONE_L_RES_MODE);
}

/**
 * @brief set precision
 *
 * @param[inout] dev: device resource
 * @param[in] prec: precision level
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_set_precision(INOUT SR_RSRC_T *dev, IN CONST SR_LT_PREC_E *prec)
{
    if ((prec == NULL) || (*prec >= SR_LT_PREC_INVALID)) {
        return OPRT_INVALID_PARM;
    }

    dev->info[BH1750_RSRC_INDEX_PREC] = *prec;
    __bh1750_start_periodic_measurement(dev);

    return OPRT_OK;
}

/**
 * @brief set frequency
 *
 * @param[inout] dev: device resource
 * @param[in] freq: frequency
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_set_frequency(INOUT SR_RSRC_T *dev, IN CONST SR_LT_PREC_E *freq)
{
    if ((freq == NULL) || (*freq >= SR_LT_FREQ_INVALID)) {
        return OPRT_INVALID_PARM;
    }

    dev->info[BH1750_RSRC_INDEX_PREC] = *freq;
    __bh1750_start_periodic_measurement(dev);

    return OPRT_OK;
}

/**
 * @brief calculate light
 *
 * @param[in] light: light raw data from sensor
 * @param[out] light_val: light value in °C
 *
 * @return none
 */
STATIC VOID_T __bh1750_calc_light(IN CONST USHORT_T light, OUT SR_VAL_U *light_val,IN USHORT_T resl)
{
#if (SR_CONFIG_NO_FPU == 1)
    light_val->sr_int = light * resl / 2;
    TAL_PR_ERR("light_val->sr_int=%d",light_val->sr_int);
    // light_val->sr_int = light * 175 / 65535 - 45;
#else
    // light_val->sr_float = light * 175.0f / 65535.0f - 45.0f;
    light_val->sr_float = light * resl / 2.0F;
    TAL_PR_ERR("light_val->sr_float=%0.1f",light_val->sr_float);
#endif
}

/**
 * @brief read light and humidity from bh1750
 *
 * @param[in] dev: device resource
 * @param[out] light: light value
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_read_light(IN CONST SR_RSRC_T *dev, OUT USHORT_T *light)
{
    UCHAR_T buf[2] = {0};
    OPERATE_RET ret = OPRT_OK;

    TAL_PR_ERR("[BH1750] __bh1750_read_light");

    // reset
    __bh1750_write_cmd(dev, BH1750_CMD_SOFT_RESET);

    // set mode
    // __bh1750_write_cmd(dev, dev->info[BH1750_RSRC_INDEX_MODE]);
    // __bh1750_start_periodic_measurement(dev);
    __bh1750_write_cmd(dev, BH1750_CMD_ONE_H_RES_MODE);

    // delay -- wait value return
    __bh1750_delay_ms(180);

    ret = __bh1750_read_data(dev, 2, buf); 
    if(ret != OPRT_OK)
        return ret;

    *light = ((USHORT_T)buf[0] << 8) | buf[1];

    TAL_PR_ERR("[BH1750] buf = %0x %0x light= %d",buf[0],buf[1],*light);

    return OPRT_OK;
}

/**
 * @brief soft reset
 *
 * @param[in] dev: device resource
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_soft_reset(IN CONST SR_RSRC_T *dev)
{
    __bh1750_write_cmd(dev, BH1750_CMD_SOFT_RESET);
    __bh1750_delay_ms(50);
    return OPRT_OK;
}

// /**
//  * @brief read serial number
//  *
//  * @param[in] dev: device resource
//  * @param[out] serial_nbr: serial number
//  *
//  * @return OPRT_OK on success, others on error
//  */
// STATIC OPERATE_RET __bh1750_read_serial_number(IN CONST SR_RSRC_T *dev, OUT SR_LT_SERIAL_NBR_T *serial_nbr)
// {
//     UCHAR_T buf[6] = {0};
//     OPERATE_RET ret = OPRT_OK;

//     __bh1750_write_cmd(dev, BH1750_CMD_READ_SERIALNBR);
//     __bh1750_delay_ms(20);
//     ret = __bh1750_read_data(dev, 6, buf);
//     if(ret != OPRT_OK)
//         return ret;

//     if ((CRC_ERR == __bh1750_check_crc8(buf, 2, buf[2])) ||\
//         (CRC_ERR == __bh1750_check_crc8(buf+3, 2, buf[5]))) {
//         TAL_PR_ERR("[BH1750] The received serial number can't pass the CRC8 check.");
//         return OPRT_CRC32_FAILED;
//     }

//     serial_nbr->val = ((UINT_T)buf[0] << 24) | ((UINT_T)buf[1] << 16) |\
//                       ((UINT_T)buf[3] <<  8) | ((UINT_T)buf[4]);
//     return OPRT_OK;
// }

/**
 * @brief open bh1750 device
 *
 * @param[inout] dev: device resource
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __tdd_sensor_bh1750_open(INOUT SR_RSRC_T *dev)
{
    __bh1750_write_cmd(dev, BH1750_CMD_POWER_ON);   // power on
    // __bh1750_start_periodic_measurement(dev);
    dev->info[BH1750_RSRC_INDEX_STAT] = BH1750_OPEN;
    return OPRT_OK;
}

/**
 * @brief close bh1750 device
 *
 * @param[inout] dev: device resource
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __tdd_sensor_bh1750_close(INOUT SR_RSRC_T *dev)
{
    // __bh1750_stop_periodic_measurement(dev);
    __bh1750_write_cmd(dev, BH1750_CMD_POWER_DOWN);   // power down
    dev->info[BH1750_RSRC_INDEX_STAT] = BH1750_CLOSE;
    return OPRT_OK;
}

/**
 * @brief control bh1750 device
 *
 * @param[inout] dev: device resource
 * @param[in] cmd: control command
 * @param[inout] param: command parameter, data type depends on the specified command
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __tdd_sensor_bh1750_control(INOUT SR_RSRC_T* dev, IN UCHAR_T cmd, INOUT VOID_T *param)
{
    OPERATE_RET op_ret = OPRT_OK;

    if ((BH1750_OPEN == dev->info[BH1750_RSRC_INDEX_STAT]) &&\
        (cmd == SR_LT_CMD_SET_PREC      ||\
         cmd == SR_LT_CMD_SET_FREQ      ||\
         cmd == SR_LT_CMD_SOFT_RESET )) {
        TAL_PR_ERR("[BH1750] Command <%d> is only supported when acquisition is closed.");
        return OPRT_COM_ERROR;
    }

    switch (cmd) {
    case SR_LT_CMD_SOFT_RESET:
        op_ret = __bh1750_soft_reset(dev);
        break;

    // case SR_LT_CMD_GET_SERIAL_NBR:
    //     op_ret = __bh1750_read_serial_number(dev, (SR_LT_SERIAL_NBR_T *)param);
    //     break;
        
    case SR_LT_CMD_SET_PREC:
        op_ret = __bh1750_set_precision(dev, (SR_LT_PREC_E *)param);
        break;

    case SR_LT_CMD_SET_FREQ:
        op_ret = __bh1750_set_frequency(dev, (SR_LT_FREQ_E *)param);
        break;

    // case SR_LT_CMD_SET_ALT_LIMIT:
    //     op_ret = __bh1750_set_alert_limit(dev, (SR_LT_LIMIT_T *)param);
    //     break;

    // case SR_LT_CMD_GET_ALT_LIMIT:
    //     op_ret = __bh1750_get_alert_limit(dev, (SR_LT_LIMIT_T *)param);
    //     break;

    // case SR_LT_CMD_ENABLE_ALT_PIN:
    //     op_ret = __bh1750_enable_alert(dev, (SR_LT_ALT_CFG_T *)param);
    //     break;

    // case SR_LT_CMD_DISABLE_ALT_PIN:
    //     op_ret = __bh1750_disable_alert(dev, (TUYA_GPIO_NUM_E *)param);
    //     break;

    // case SR_LT_CMD_GET_STATUS:
    //     op_ret = __bh1750_read_status(dev, (SR_LT_STATUS_U *)param);
    //     break;

    // case SR_LT_CMD_CLR_STATUS:
    //     op_ret = __bh1750_clear_status(dev);
    //     break;

    // case SR_LT_CMD_ENABLE_HEATER:
    //     op_ret = __bh1750_set_heater(dev, TRUE);
    //     break;

    // case SR_LT_CMD_DISABLE_HEATER:
    //     op_ret = __bh1750_set_heater(dev, FALSE);
    //     break;

    default:
        op_ret = OPRT_INVALID_PARM;
        TAL_PR_ERR("[BH1750] Command <%d> is invalid.", cmd);
        break;
    }

    return op_ret;
}

/**
 * @brief read data from bh1750 device
 *
 * @param[in] dev: device
 * @param[out] ele_data: element data
 * @param[in] ele_num: number of elements
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __tdd_sensor_bh1750_read(IN SR_RSRC_T* dev, OUT SR_ELE_DATA_T *ele_data, IN UCHAR_T ele_num)
{
    USHORT_T light = 0;

    TAL_PR_ERR("[BH1750] __tdd_sensor_bh1750_read");

    OPERATE_RET op_ret = __bh1750_read_light(dev, &light);
    if (op_ret != OPRT_OK) {
        return op_ret;
    }

    for (UCHAR_T i = 0; i < ele_num; i++) {
        switch (ele_data[i].id) {
        case SR_LT_ELE_ID_LIGHT:
            TAL_PR_ERR("[BH1750] get value. resl=%d",dev->info[BH1750_RSRC_INDEX_RESL]);
            __bh1750_calc_light(light, &ele_data[i].val, (USHORT_T)dev->info[BH1750_RSRC_INDEX_RESL]);
            // ele_data[i].val = ele_data[i].val * (SR_VAL_U)(dev->info[BH1750_RSRC_INDEX_RESL]);
            break;
            
        default:
            TAL_PR_ERR("[BH1750] Element ID: %d is invalid.", ele_data[i].id);
            break;
        }
    }
    return OPRT_OK;
}

/**
 * @brief register bh1750 device
 *
 * @param[in] name: device name
 * @param[in] i2c_cfg: i2c configuration
 * @param[in] meas_cfg: measurement configuration
 *
 * @return OPRT_OK on success, others on error
 */
OPERATE_RET tdd_sensor_bh1750_register(IN CHAR_T *name, IN SR_LT_I2C_CFG_T i2c_cfg, IN SR_LT_MEAS_CFG_T meas_cfg)
{
    // check param
    if (i2c_cfg.gpio.scl == i2c_cfg.gpio.sda) {
        return OPRT_INVALID_PARM;
    }

    // I2C init
    tdd_sensor_i2c_init(i2c_cfg.port, i2c_cfg.gpio);

    // save resourse information
    SR_RSRC_T resource = {0};
    resource.port = i2c_cfg.port;
    resource.handle = NULL;
    resource.info[BH1750_RSRC_INDEX_STAT] = BH1750_CLOSE;
    resource.info[BH1750_RSRC_INDEX_ADDR] = i2c_cfg.addr;
    resource.info[BH1750_RSRC_INDEX_PREC] = meas_cfg.prec;
    resource.info[BH1750_RSRC_INDEX_FREQ] = meas_cfg.freq;

    switch (meas_cfg.prec) {
        case SR_LT_PREC_HIGH: 
            resource.info[BH1750_RSRC_INDEX_RESL] = 2;//1
            break;
        case SR_LT_PREC_MEDIUM:
            resource.info[BH1750_RSRC_INDEX_RESL] = 1;//0.5
            break;
        case SR_LT_PREC_LOW:
            resource.info[BH1750_RSRC_INDEX_RESL] = 82;//41
            break;
        default:
            resource.info[BH1750_RSRC_INDEX_RESL] = 1;//2
            break;
    }
    

    // define driver interfaces
    STATIC SR_INTFS_T s_intfs;
    s_intfs.open = __tdd_sensor_bh1750_open;
    s_intfs.close = __tdd_sensor_bh1750_close;
    s_intfs.control = __tdd_sensor_bh1750_control;
    s_intfs.read_ele = __tdd_sensor_bh1750_read;

    // register the device
    OPERATE_RET op_ret = tdl_sensor_register(name, &s_intfs, SR_LT_ELE_NUM, sg_ele_val_tp, &resource);
    if (OPRT_OK != op_ret) {
        return op_ret;
    }

    return OPRT_OK;
}

app_light.c

/**
 * @file app_light.c
 * @brief RH-T sensor application demo
 * @version 0.1
 * @date 2022-09-07
 */

#include "app_light.h"
#include "tdl_sensor_hub.h"
#include "tdd_sensor_light.h"
#include "tkl_memory.h"
#include "tal_sw_timer.h"
#include "tal_log.h"
#include "tuya_iot_com_api.h"
#include "tuya_wifi_status.h"
#include "tuya_ws_db.h"

/***********************************************************
************************macro define************************
***********************************************************/

/**
 * @brief alert code
 */
#define ALT_LOWER       0
#define ALT_UPPER       1
#define ALT_CANCEL      2

/***********************************************************
***********************typedef define***********************
***********************************************************/
/**
 * @brief DP data typedef
 */
typedef struct {
    TY_OBJ_DP_VALUE_U light;
    TY_OBJ_DP_VALUE_U light_alert;
} LT_DP_DATA_T;

/**
 * @brief flag typedef
 */
typedef struct {
    UCHAR_T turn_on         : 1;
    UCHAR_T light_change    : 1;
    UCHAR_T alert           : 1;
    UCHAR_T reserved        : 4;
} LT_FLAG_T;

/***********************************************************
********************function declaration********************
***********************************************************/

/***********************************************************
***********************variable define**********************
***********************************************************/
/**
 * @brief bh1750 process
 */
STATIC SENSOR_HANDLE_T sg_bh1750_handle = NULL;
STATIC SR_LT_STATUS_U sg_bh1750_status;
STATIC SR_LT_LIMIT_T sg_bh1750_alert_limit;
STATIC LT_FLAG_T sg_bh1750_flag;
STATIC TIMER_ID sg_bh1750_report_timer;

/**
 * @brief DP process
 */
STATIC LT_DP_DATA_T sg_lt_dp_data;

/***********************************************************
***********************function define**********************
***********************************************************/
/**
 * @brief report one dp data
 *
 * @param[in] dp_id: DP ID
 * @param[in] dp_type: DP type
 * @param[in] dp_value: DP value
 *
 * @return none
 */
STATIC VOID_T __repo_one_dp_data(CONST UCHAR_T dp_id, CONST UCHAR_T dp_type, CONST TY_OBJ_DP_VALUE_U dp_value)
{
    GW_WIFI_NW_STAT_E wifi_stat = STAT_LOW_POWER;
    get_wf_gw_nw_status(&wifi_stat);
    if (wifi_stat <= STAT_AP_STA_DISC || wifi_stat == STAT_STA_DISC) {
        return;
    }

    TY_OBJ_DP_S dp_repo;

    dp_repo.dpid = dp_id;
    dp_repo.type = dp_type;
    dp_repo.time_stamp = 0;

    switch (dp_type) {
    case PROP_BOOL:
        dp_repo.value.dp_bool = dp_value.dp_bool;
        break;

    case PROP_VALUE:
        dp_repo.value.dp_value = dp_value.dp_value;
        break;

    case PROP_ENUM:
        dp_repo.value.dp_enum = dp_value.dp_enum;
        break;

    case PROP_STR:
        dp_repo.value.dp_str = dp_value.dp_str;
        break;

    case PROP_BITMAP:
        dp_repo.value.dp_bitmap = dp_value.dp_bitmap;
        break;

    default:
        break;
    }

    TAL_PR_INFO("repo_one_dp_data ID:%d", dp_repo.dpid);
    OPERATE_RET op_ret = dev_report_dp_json_async(NULL, &dp_repo, 1);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("__repo_one_dp_data -- dev_report_dp_json_async, error code: %d.", op_ret);
    }
}


/**
 * @brief data ready inform
 *
 * @param[in] name: device name
 * @param[in] ele_num: number of elements
 * @param[in] ele_data: element data
 *
 * @return none
 */
STATIC VOID_T __bh1750_inform_cb(CHAR_T* name, UCHAR_T ele_num, SR_ELE_BUFF_T *ele_data)
{
    INT_T light;

    for (UCHAR_T i = 0; i < ele_num; i++) {
        if (ele_data[i].id == SR_LT_ELE_ID_LIGHT) {
            light = (INT_T)(ele_data[i].val[0].sr_float * LIGHT_SCALE);
            
            TAL_PR_INFO("Light: %d sg_lt_dp_data.light.dp_value: %d", light, sg_lt_dp_data.light.dp_value);
            if (light != sg_lt_dp_data.light.dp_value) {
                if ((light > (sg_lt_dp_data.light.dp_value + APP_LIGHT_REPORT_INTERVAL)) || \
                    ((light + APP_LIGHT_REPORT_INTERVAL) < sg_lt_dp_data.light.dp_value)) {

                    sg_lt_dp_data.light.dp_value = light;
                    sg_bh1750_flag.light_change = TRUE;
                    TAL_PR_INFO("Light change. Enable report");
                }

            }
        } 
    }
}

/**
 * @brief bh1750 alert callback
 *
 * @param none
 *
 * @return none
 */
STATIC VOID_T __bh1750_alert_cb(VOID_T *args)
{
    sg_bh1750_flag.alert = TRUE;
}

/**
 * @brief bh1750 register
 *
 * @param none
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_register(VOID_T)
{
    OPERATE_RET op_ret;

    TAL_PR_DEBUG("Youkai __bh1750_register");

    SR_I2C_GPIO_T i2c_gpio = {
        .scl = BH1750_SCL_PIN,
        .sda = BH1750_SDA_PIN
    };
    SR_LT_I2C_CFG_T bh1750_i2c_cfg = {
        .port = 0,
        .addr = SR_I2C_ADDR_BH1750_A,   // GND
        .gpio = i2c_gpio
    };

    SR_LT_MEAS_CFG_T bh1750_meas_cfg = {
        .prec = SR_LT_PREC_HIGH,
        .freq = SR_LT_FREQ_CON,
        // .mode = BH1750_CMD_CON_H_RES_MODE
    };

    op_ret = tdd_sensor_bh1750_register("BH1750", bh1750_i2c_cfg, bh1750_meas_cfg);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("tdd_sensor_bh1750_register, error code: %d.", op_ret);
        return op_ret;
    }

    op_ret = tdl_sensor_dev_find("BH1750", &sg_bh1750_handle);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("tdl_sensor_dev_find, error code: %d.", op_ret);
        return op_ret;
    }

    return OPRT_OK;
}

/**
 * @brief clear status
 *
 * @param none
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_clear_status(VOID_T)
{
    OPERATE_RET op_ret;

    op_ret = tdl_sensor_dev_config(sg_bh1750_handle, SR_LT_CMD_CLR_STATUS, NULL);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("SR_LT_CMD_CLR_STATUS, error code: %d.", op_ret);
        return op_ret;
    }

    op_ret = tdl_sensor_dev_config(sg_bh1750_handle, SR_LT_CMD_GET_STATUS, &sg_bh1750_status);
    if (op_ret != OPRT_OK) {
        TAL_PR_ERR("SR_LT_CMD_GET_STATUS, error code: %d.", op_ret);
        return op_ret;
    }

    TAL_PR_DEBUG("Status <alert pending>: %d.", sg_bh1750_status.bit.alert_pending);
    TAL_PR_DEBUG("Status <light alert>: %d.", sg_bh1750_status.bit.light_alert);

    return OPRT_OK;
}


/**
 * @brief bh1750 set alert
 *
 * @param none
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_set_alert(VOID_T)
{
    OPERATE_RET op_ret;

    // set alert limit
    sg_bh1750_alert_limit.light_high_set.sr_float = 125.0f;
    sg_bh1750_alert_limit.light_high_clear.sr_float = sg_bh1750_alert_limit.light_high_set.sr_float - 5.0f;
    sg_bh1750_alert_limit.light_low_set.sr_float = -40.0f;
    sg_bh1750_alert_limit.light_low_clear.sr_float = sg_bh1750_alert_limit.light_low_set.sr_float + 5.0f;

    op_ret = tdl_sensor_dev_config(sg_bh1750_handle, SR_LT_CMD_SET_ALT_LIMIT, &sg_bh1750_alert_limit);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("SR_LT_CMD_SET_ALT_LIMIT, error code: %d.", op_ret);
        return op_ret;
    }

    // clear alert status
    op_ret = __bh1750_clear_status();
    if (op_ret != OPRT_OK) {
        return op_ret;
    }

    // enable alert function
    SR_LT_ALT_CFG_T bh1750_alert_cfg;
    bh1750_alert_cfg.pin = BH1750_ALT_PIN;
    bh1750_alert_cfg.irq.mode = TUYA_GPIO_IRQ_RISE;
    bh1750_alert_cfg.irq.cb = __bh1750_alert_cb;
    bh1750_alert_cfg.irq.arg = NULL;

    op_ret = tdl_sensor_dev_config(sg_bh1750_handle, SR_LT_CMD_ENABLE_ALT_PIN, &bh1750_alert_cfg);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("SR_LT_CMD_ENABLE_ALT_PIN, error code: %d.", op_ret);
        return op_ret;
    }

    return OPRT_OK;
}

/**
 * @brief bh1750 open
 *
 * @param none
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_open(VOID_T)
{
    TAL_PR_DEBUG("Youkai __bh1750_open");

    if (sg_bh1750_flag.turn_on) {
        TAL_PR_ERR("The device is already turned on.");
        return OPRT_COM_ERROR;
    }

    OPERATE_RET op_ret;
    SR_DEV_CFG_T bh1750_cfg;
    tkl_system_memset(&bh1750_cfg, 0, SIZEOF(SR_DEV_CFG_T));

    bh1750_cfg.mode.trig_mode = SR_MODE_POLL_SOFT_TM;
    bh1750_cfg.mode.poll_intv_ms = APP_LIGHT_READ_CYCLE;
    bh1750_cfg.inform_cb.ele = __bh1750_inform_cb;
    bh1750_cfg.fifo_size = 1;
    bh1750_cfg.ele_sub = NULL;

    op_ret = tdl_sensor_dev_open(sg_bh1750_handle, &bh1750_cfg);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("tdl_sensor_dev_open, error code: %d.", op_ret);
        return op_ret;
    }

    sg_bh1750_flag.turn_on = TRUE;
    TAL_PR_INFO("Open device successfully.");

    return OPRT_OK;
}

/**
 * @brief bh1750 close
 *
 * @param none
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_close(VOID_T)
{
    if (!sg_bh1750_flag.turn_on) {
        TAL_PR_ERR("The device is already turned off.");
        return OPRT_COM_ERROR;
    }

    OPERATE_RET op_ret = tdl_sensor_dev_close(sg_bh1750_handle);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("tdl_sensor_dev_close, error code: %d.", op_ret);
        return op_ret;
    }

    sg_bh1750_flag.turn_on = FALSE;
    TAL_PR_INFO("Close device successfully.");

    return OPRT_OK;
}

/**
 * @brief get alert code
 *
 * @param[in] cur_val: current value
 * @param[in] high_lim: high set limit
 * @param[in] low_lim: low set limit
 *
 * @return alert code
 */
STATIC UINT_T __get_alert_code(CONST FLOAT_T cur_val, CONST FLOAT_T high_lim, CONST FLOAT_T low_lim)
{
    UINT_T code;
    FLOAT_T diff_abs_h, diff_abs_l;

    if (cur_val >= high_lim) {
        diff_abs_h = cur_val - high_lim;
    } else {
        diff_abs_h = high_lim - cur_val;
    }
    if (cur_val >= low_lim) {
        diff_abs_l = cur_val - low_lim;
    } else {
        diff_abs_l = low_lim - cur_val;
    }

    if (diff_abs_h < diff_abs_l) {
        code = ALT_UPPER;
    } else {
        code = ALT_LOWER;
    }
    
    return code;
}


/**
 * @brief bh1750 alert occur handler
 *
 * @param none
 *
 * @return none
 */
STATIC VOID_T __bh1750_alert_occur_handler(VOID_T)
{
    OPERATE_RET op_ret = tdl_sensor_dev_config(sg_bh1750_handle, SR_LT_CMD_GET_STATUS, &sg_bh1750_status);
    if (op_ret != OPRT_OK) {
        TAL_PR_ERR("SR_LT_CMD_GET_STATUS, error code: %d.", op_ret);
        return;
    }

    FLOAT_T cur_val;

    if (sg_bh1750_status.bit.light_alert) {
        if (ALT_CANCEL == sg_lt_dp_data.light_alert.dp_enum) {
            TAL_PR_INFO("Light alert occurred.");
            cur_val = sg_lt_dp_data.light.dp_value / (10.0f * LIGHT_SCALE);
            sg_lt_dp_data.light_alert.dp_enum = __get_alert_code(cur_val,\
                                                                sg_bh1750_alert_limit.light_high_set.sr_float,\
                                                                sg_bh1750_alert_limit.light_low_set.sr_float);
            __repo_one_dp_data(DP_ID_LIGHT_ALT, PROP_ENUM, sg_lt_dp_data.light_alert);
        }
    } else {
        if (sg_lt_dp_data.light_alert.dp_enum != ALT_CANCEL) {
            TAL_PR_INFO("Light alert canceled.");
            sg_lt_dp_data.light_alert.dp_enum = ALT_CANCEL;
            __repo_one_dp_data(DP_ID_LIGHT_ALT, PROP_ENUM, sg_lt_dp_data.light_alert);
        }
    }

    if (!sg_bh1750_status.bit.light_alert) {
        sg_bh1750_flag.alert = FALSE;
    }
}

/**
 * @brief bh1750 report timer callback
 *
 * @param[in] timer_id: timer ID
 * @param[in] arg: argument
 *
 * @return none
 */
STATIC VOID_T __bh1750_report_timer_cb(TIMER_ID timer_id, VOID_T *arg)
{
    // if (sg_bh1750_flag.alert) {
    //     __bh1750_alert_occur_handler();
    // }



    if (sg_bh1750_flag.light_change) {
        TAL_PR_INFO("light change report.");
        sg_bh1750_flag.light_change = FALSE;
        __repo_one_dp_data(DP_ID_LIGHT, PROP_VALUE, sg_lt_dp_data.light);
    }

}

/**
 * @brief light main
 *
 * @param none
 *
 * @return OPRT_OK on success, others on error
 */
OPERATE_RET app_light_init(VOID_T)
{
    OPERATE_RET op_ret;
    BOOL_T is_exist = FALSE;

    tkl_system_memset(&sg_bh1750_flag, 0, SIZEOF(LT_FLAG_T));

    TAL_PR_ERR("app_light_init");

    sg_lt_dp_data.light.dp_value = 0;
    sg_lt_dp_data.light_alert.dp_enum = ALT_CANCEL;
    sg_bh1750_status.word = 0;

    op_ret = __bh1750_register();
    if (OPRT_OK != op_ret) {
        return op_ret;
    }

    // op_ret = __bh1750_set_alert();
    // if (OPRT_OK != op_ret) {
    //     return op_ret;
    // }

    op_ret = __bh1750_open();
    if (OPRT_OK != op_ret) {
        return op_ret;
    }

    op_ret = tal_sw_timer_create(__bh1750_report_timer_cb, NULL, &sg_bh1750_report_timer);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("tal_sw_timer_create -- sg_bh1750_report_timer, error code: %d.", op_ret);
        return op_ret;
    } else {
        tal_sw_timer_start(sg_bh1750_report_timer, APP_LIGHT_REPORT_CYCLE, TAL_TIMER_CYCLE);
    }


    //read alert limit data
    // wd_common_exist(KEY_NAME, &is_exist);
    // if (TRUE == is_exist) {
    //     BYTE_T  *read_buf = NULL;
    //     UINT_T read_len;
    //     op_ret = wd_common_read(KEY_NAME, &read_buf, &read_len);
    //     if (OPRT_OK != op_ret) {
    //         TAL_PR_ERR("wd_common_read %s error code: %d,", KEY_NAME, op_ret);
    //         return op_ret;
    //     }

    //     SR_LT_LIMIT_T *data = (SR_LT_LIMIT_T *)read_buf;
    //     sg_bh1750_alert_limit.light_high_set.sr_float = data->light_high_set.sr_float;
    //     sg_bh1750_alert_limit.light_low_set.sr_float = data->light_low_set.sr_float;

    //     if (NULL != read_buf) {
    //         wd_common_free_data(read_buf);
    //         read_buf = NULL;
    //     }
    // } else {
    //     //set default value
    //     sg_bh1750_alert_limit.light_high_set.sr_float = 125.0f;
    //     sg_bh1750_alert_limit.light_low_set.sr_float = -40.0f;
    //     op_ret = wd_common_write(KEY_NAME, (BYTE_T *)&sg_bh1750_alert_limit, sizeof(sg_bh1750_alert_limit));
    //     if (OPRT_OK != op_ret) {
    //         TAL_PR_ERR("wd_common_write %s error code: %d,", KEY_NAME, op_ret);

    //         return op_ret;
    //     }
    // }

    return OPRT_OK;
}

/**
 * @brief bh1750 set alert by cloud
 *
 * @param none
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_set_alert_by_cloud(VOID_T)
{
    OPERATE_RET op_ret;

    sg_bh1750_alert_limit.light_high_clear.sr_float = sg_bh1750_alert_limit.light_high_set.sr_float;
    sg_bh1750_alert_limit.light_low_clear.sr_float = sg_bh1750_alert_limit.light_low_set.sr_float;

    op_ret = wd_common_write(KEY_NAME, (BYTE_T *)&sg_bh1750_alert_limit, sizeof(sg_bh1750_alert_limit));
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("wd_common_write %s error code: %d,", KEY_NAME, op_ret);

        return op_ret;
    }

    op_ret = tdl_sensor_dev_config(sg_bh1750_handle, SR_LT_CMD_SET_ALT_LIMIT, &sg_bh1750_alert_limit);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("SR_LT_CMD_SET_ALT_LIMIT, error code: %d.", op_ret);
        return op_ret;
    }

    op_ret = __bh1750_clear_status();
    if (OPRT_OK != op_ret) {
        return op_ret;
    }

    return OPRT_OK;
}

/**
 * @brief switch device
 *
 * @param[in] enabled: TRUE on enabled, FALSE on disabled
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __switch_dev_by_cloud(CONST BOOL_T enabled)
{
    OPERATE_RET op_ret;
    if (enabled) {
        op_ret = __bh1750_open();
    } else {
        op_ret = __bh1750_close();
    }
    return op_ret;
}

/**
 * @brief DP processing
 *
 * @param[in] dp: dp data
 *
 * @return none
 */
VOID_T app_light_dp_proc(CONST TY_OBJ_DP_S *dp)
{
    OPERATE_RET op_ret;

    switch (dp->dpid) {
    case DP_ID_LIGHT_MAX:
        sg_bh1750_alert_limit.light_high_set.sr_float = dp->value.dp_value / (10.0f * LIGHT_SCALE);
        TAL_PR_INFO("[APP] Set the maximum lighterature to %.1f.", sg_bh1750_alert_limit.light_high_set.sr_float);
        op_ret = __bh1750_set_alert_by_cloud();
        break;

    case DP_ID_LIGHT_MIN:
        sg_bh1750_alert_limit.light_low_set.sr_float = dp->value.dp_value / (10.0f * LIGHT_SCALE);
        TAL_PR_INFO("[APP] Set the minimum lighterature to %.1f.", sg_bh1750_alert_limit.light_low_set.sr_float);
        op_ret = __bh1750_set_alert_by_cloud();
        break;

    case DP_ID_SWITCH:
        TAL_PR_INFO("[APP] Switch device: %d.", dp->value.dp_bool);
        op_ret = __switch_dev_by_cloud(dp->value.dp_bool);
        break;

    default:
        op_ret = OPRT_INVALID_PARM;
        break;
    }

    if (OPRT_OK == op_ret) {
        op_ret = dev_report_dp_json_async(NULL, dp, 1);
        if (OPRT_OK != op_ret) {
            TAL_PR_ERR("app_light_dp_proc -- dev_report_dp_json_async, error code: %d.", op_ret);
        }
    }

    TAL_PR_INFO("app_light_dp_proc: %d", op_ret);
}

/**
 * @brief report all DP data
 *
 * @param none
 *
 * @return none
 */
VOID_T app_light_repo_all_dp(VOID_T)
{
    GW_WIFI_NW_STAT_E wifi_stat = STAT_LOW_POWER;
    get_wf_gw_nw_status(&wifi_stat);
    if (wifi_stat <= STAT_AP_STA_DISC || wifi_stat == STAT_STA_DISC) {
        return;
    }

    TY_OBJ_DP_S *dp_arr = (TY_OBJ_DP_S *)tkl_system_malloc(MAX_DP_NUM*SIZEOF(TY_OBJ_DP_S));
    if (NULL == dp_arr) {
        TAL_PR_ERR("dp_arr malloc failed.");
        return;
    }

    tkl_system_memset(dp_arr, 0, MAX_DP_NUM*SIZEOF(TY_OBJ_DP_S));

    dp_arr[0].dpid = DP_ID_LIGHT;
    dp_arr[0].type = PROP_VALUE;
    dp_arr[0].time_stamp = 0;
    dp_arr[0].value.dp_value = sg_lt_dp_data.light.dp_value;

    dp_arr[2].dpid = DP_ID_LIGHT_MAX;
    dp_arr[2].type = PROP_VALUE;
    dp_arr[2].time_stamp = 0;
    dp_arr[2].value.dp_value = (INT_T)(sg_bh1750_alert_limit.light_high_set.sr_float * (10 * LIGHT_SCALE));

    dp_arr[3].dpid = DP_ID_LIGHT_MIN;
    dp_arr[3].type = PROP_VALUE;
    dp_arr[3].time_stamp = 0;
    dp_arr[3].value.dp_value = (INT_T)(sg_bh1750_alert_limit.light_low_set.sr_float * (10 * LIGHT_SCALE));

    dp_arr[6].dpid = DP_ID_LIGHT_ALT;
    dp_arr[6].type = PROP_ENUM;
    dp_arr[6].time_stamp = 0;
    dp_arr[6].value.dp_enum = sg_lt_dp_data.light_alert.dp_enum;

    dp_arr[8].dpid = DP_ID_SWITCH;
    dp_arr[8].type = PROP_BOOL;
    dp_arr[8].time_stamp = 0;
    dp_arr[8].value.dp_bool = sg_bh1750_flag.turn_on;


    OPERATE_RET op_ret = dev_report_dp_json_async(NULL, dp_arr, MAX_DP_NUM);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("app_light_repo_all_dp -- dev_report_dp_json_async, error code: %d.", op_ret);
    } else {
        TAL_PR_INFO("app_light_repo_all_dp: %d", op_ret);
    }
    tkl_system_free(dp_arr);
    dp_arr = NULL;
}

tuya_app_main.c

/**
 * @file tuya_app_main.c
 * @author www.tuya.com
 * @brief tuya_app_main module is used to 
 * @version 0.1
 * @date 2022-10-28
 *
 * @copyright Copyright (c) tuya.inc 2022
 *
 */

#include "tuya_cloud_types.h"
#include "tuya_iot_wifi_api.h"
#include "tuya_ws_db.h"
#include "gw_intf.h"
#include "tal_log.h"
#include "tal_wifi.h"
#include "tal_uart.h"
#include "mf_test.h"
#if defined(ENABLE_LWIP) && (ENABLE_LWIP == 1)
#include "lwip_init.h"
#endif

#include "app_led.h"
#include "app_key.h"

#include "app_light.h"

/***********************************************************
************************macro define************************
***********************************************************/


/* The registration code here does not work, you need to apply for a new one.
 * https://developer.tuya.com/cn/docs/iot/lisence-management?id=Kb4qlem97idl0
 */
// #define UUID     "f998xxxxxxxx2409"
// #define AUTHKEY  "WEHAxxxxxxxxxxxxxxxxxxxxxxxxVVkf"

/* network button, LED pin */
#define KEY_PIN 7
#define LED_PIN 26

/* Compatible with TuyaOS 3.3.x */
#ifndef TUYA_UART_NUM_0
#define TUYA_UART_NUM_0 UART_NUM_0
#endif

/***********************************************************
***********************typedef define***********************
***********************************************************/


/***********************************************************
********************function declaration********************
***********************************************************/


/***********************************************************
***********************variable define**********************
***********************************************************/
/* app thread handle */
STATIC THREAD_HANDLE ty_app_thread = NULL;

/***********************************************************
***********************function define**********************
***********************************************************/

/**
 * @brief SOC device upgrade entry
 *
 * @param[in] fw: firmware info
 *
 * @return OPRT_OK on success. Others on error, please refer to "tuya_error_code.h".
 */
STATIC OPERATE_RET __soc_dev_rev_upgrade_info_cb(IN CONST FW_UG_S *fw)
{
    TAL_PR_DEBUG("SOC Rev Upgrade Info");
    TAL_PR_DEBUG("fw->tp:%d", fw->tp);
    TAL_PR_DEBUG("fw->fw_url:%s", fw->fw_url);
    TAL_PR_DEBUG("fw->fw_hmac:%s", fw->fw_hmac);
    TAL_PR_DEBUG("fw->sw_ver:%s", fw->sw_ver);
    TAL_PR_DEBUG("fw->file_size:%u", fw->file_size);

    return OPRT_OK;
}

/**
 * @brief SOC device cloud state change callback
 *
 * @param[in] status: current status
 *
 * @return none
 */
STATIC VOID_T __soc_dev_status_changed_cb(IN CONST GW_STATUS_E status)
{
    TAL_PR_DEBUG("SOC TUYA-Cloud Status:%d", status);
    return;
}

/**
 * @brief SOC device DP query entry
 *
 * @param[in] dp_qry: DP query list
 *
 * @return none
 */
STATIC VOID_T __soc_dev_dp_query_cb(IN CONST TY_DP_QUERY_S *dp_qry)
{
    UINT32_T index = 0;

    TAL_PR_DEBUG("SOC Rev DP Query Cmd");
    if (dp_qry->cid != NULL) {
        TAL_PR_ERR("soc not have cid.%s", dp_qry->cid);
    }

    if (dp_qry->cnt == 0) {
        TAL_PR_DEBUG("soc rev all dp query");
        app_light_repo_all_dp();
    } else {
        TAL_PR_DEBUG("soc rev dp query cnt:%d", dp_qry->cnt);
        for (index = 0; index < dp_qry->cnt; index++) {
            TAL_PR_DEBUG("rev dp query:%d", dp_qry->dpid[index]);
            
        }
    }

    return;
}

/**
 * @brief SOC device format command data delivery entry
 *
 * @param[in] dp: obj dp info
 *
 * @return none
 */
STATIC VOID_T __soc_dev_obj_dp_cmd_cb(IN CONST TY_RECV_OBJ_DP_S *dp)
{
    UINT32_T index = 0;

    TAL_PR_DEBUG("SOC Rev DP Obj Cmd t1:%d t2:%d CNT:%u", dp->cmd_tp, dp->dtt_tp, dp->dps_cnt);
    if (dp->cid != NULL) {
        TAL_PR_ERR("soc not have cid.%s", dp->cid);
    }

    for (index = 0; index < dp->dps_cnt; index++) {
        app_light_dp_proc(&(dp->dps[index]));
    }

    return;
}

/**
 * @brief SOC device transparently transmits command data delivery entry
 *
 * @param[in] dp: raw dp info
 *
 * @return none
 */
STATIC VOID_T __soc_dev_raw_dp_cmd_cb(IN CONST TY_RECV_RAW_DP_S *dp)
{
    TAL_PR_DEBUG("SOC Rev DP Raw Cmd t1:%d t2:%d dpid:%d len:%u", dp->cmd_tp, dp->dtt_tp, dp->dpid, dp->len);
    if (dp->cid != NULL) {
        TAL_PR_ERR("soc not have cid.%s", dp->cid);
    }

    return;
}

/**
 * @brief SOC device process restart request entry
 *
 * @param[in] type: gateway reset type
 *
 * @return none
 */
STATIC VOID_T __soc_dev_restart_req_cb(GW_RESET_TYPE_E type)
{
    TAL_PR_DEBUG("SOC Rev Restart Req %d", type);
    if (GW_RESET_DATA_FACTORY != type) {
        // UserTODO Device process restart
        tal_system_reset();
    }

    return;
}

/**
 * @brief SOC external network status change callback
 *
 * @param[in] stat: curr network status
 *
 * @return none
 */
STATIC VOID __soc_dev_net_status_cb(IN CONST GW_WIFI_NW_STAT_E stat)
{
    TAL_PR_DEBUG("network status:%d", stat);

    STATIC BOOL_T proc_flag = FALSE;
    if ((FALSE == proc_flag) &&\
        (STAT_AP_STA_CONN == stat || STAT_STA_CONN <= stat)) {
        app_light_repo_all_dp();
        TAL_PR_INFO("WF");
        proc_flag = TRUE;
    }

    if ((TRUE == proc_flag) &&\
        (STAT_AP_STA_DISC == stat || STAT_STA_DISC == stat)) {
        proc_flag = FALSE;
    }

    return;
}

/**
 * @brief mf uart init
 *
 * @param[in] baud: Baud rate
 * @param[in] bufsz: uart receive buffer size
 *
 * @return none
 */
VOID mf_uart_init_callback(UINT_T baud, UINT_T bufsz)
{
    TAL_UART_CFG_T cfg;
    memset(&cfg, 0, sizeof(TAL_UART_CFG_T));
    cfg.base_cfg.baudrate = baud;
    cfg.base_cfg.databits = TUYA_UART_DATA_LEN_8BIT;
    cfg.base_cfg.parity = TUYA_UART_PARITY_TYPE_NONE;
    cfg.base_cfg.stopbits = TUYA_UART_STOP_LEN_1BIT;
    cfg.rx_buffer_size = bufsz;

    tal_uart_init(TUYA_UART_NUM_0, &cfg);

    return;
}

/**
 * @brief mf uart free
 *
 * @param[in] none
 *
 * @return none
 */
VOID mf_uart_free_callback(VOID)
{
    tal_uart_deinit(TUYA_UART_NUM_0);
    return;
}

/**
 * @brief mf uart send function
 *
 * @param[in] data: send data
 * @param[in] len: send data length
 * 
 * @return none
 */
VOID mf_uart_send_callback(IN BYTE_T *data, IN CONST UINT_T len)
{
    tal_uart_write(TUYA_UART_NUM_0, data, len);
    return;
}

/**
 * @brief mf uart receive function
 *
 * @param[in] buf: receive buffer
 * @param[in] len: receive buffer max length
 *
 * @return receive data length
 */
UINT_T mf_uart_recv_callback(OUT BYTE_T *buf, IN CONST UINT_T len)
{
    return tal_uart_read(TUYA_UART_NUM_0, buf, len);
}

/**
 * @brief Product test callback function
 *
 * @param[in] cmd: Command
 * @param[in] data: data
 * @param[out] ret_data: Resulting data
 * @param[out] ret_len: Resulting data length
 * 
 * @return OPRT_OK on success. Others on error, please refer to "tuya_error_code.h".
 */
OPERATE_RET mf_user_product_test_callback(USHORT_T cmd, UCHAR_T *data, UINT_T len, OUT UCHAR_T **ret_data, OUT USHORT_T *ret_len)
{
    /* USER todo */
    return OPRT_OK;
}

/**
 * @brief mf configure write callback functions
 *
 * @param[in] none
 *
 * @return none
 */
VOID mf_user_callback(VOID)
{
    return ;
}

/**
 * @brief Callback function before entering the production test
 *
 * @param[in] none
 *
 * @return none
 */
VOID mf_user_enter_mf_callback(VOID)
{
    return ;
}

BOOL_T mf_gpio_test_cb(IN CONST CHAR_T *in, OUT CHAR_T *out)
{
    return TRUE;
}


BOOL_T mf_pre_gpio_test_cb(VOID)
{
    return TRUE;
}

/**
 * @brief SOC device initialization
 *
 * @param[in] none
 *
 * @return OPRT_OK on success. Others on error, please refer to "tuya_error_code.h".
 */
OPERATE_RET __soc_device_init(VOID_T)
{
    OPERATE_RET rt = OPRT_OK;

#if (defined(UUID) && defined(AUTHKEY))
    ws_db_init_mf();

    /* Set authorization information
     * Note that if you use the default authorization information of the code, there may be problems of multiple users and conflicts, 
     * so try to use all the authorizations purchased from the tuya iot platform.
     * Buying guide: https://developer.tuya.com/cn/docs/iot/lisence-management?id=Kb4qlem97idl0.
     * You can also apply for two authorization codes for free in the five-step hardware development stage of the Tuya IoT platform.
     * Authorization information can also be written through the production testing tool.
     * When the production testing function is started and the authorization is burned with the Tuya Cloud module tool, 
     * please comment out this piece of code.
     */
    WF_GW_PROD_INFO_S prod_info = {UUID, AUTHKEY};
    TUYA_CALL_ERR_RETURN(tuya_iot_set_wf_gw_prod_info(&prod_info));
#else
    // 产测初始化, 注册函数需要应用实现,其中串口驱动不需要应用提供
    MF_IMPORT_INTF_S intf = {0};

    intf.uart_init = mf_uart_init_callback;
    intf.uart_free = mf_uart_free_callback;
    intf.uart_send = mf_uart_send_callback;
    intf.uart_recv = mf_uart_recv_callback;

    intf.gpio_test = mf_gpio_test_cb;
    intf.mf_user_product_test = mf_user_product_test_callback;
    intf.user_callback = mf_user_callback;
    intf.user_enter_mf_callback = mf_user_enter_mf_callback;
    intf.user_pre_gpio_test = mf_pre_gpio_test_cb;

    TAL_PR_ERR("mf_init APP_BIN_NAME[%s] USER_SW_VER[%s]", APP_BIN_NAME, USER_SW_VER);
    
    TUYA_CALL_ERR_RETURN(mf_init(&intf, APP_BIN_NAME, USER_SW_VER, TRUE));
#endif

    /* Initialize TuyaOS product information */
    TY_IOT_CBS_S iot_cbs = {0};
    iot_cbs.gw_status_cb = __soc_dev_status_changed_cb;
    iot_cbs.gw_ug_cb = __soc_dev_rev_upgrade_info_cb;
    iot_cbs.gw_reset_cb = __soc_dev_restart_req_cb;
    iot_cbs.dev_obj_dp_cb = __soc_dev_obj_dp_cmd_cb;
    iot_cbs.dev_raw_dp_cb = __soc_dev_raw_dp_cmd_cb;
    iot_cbs.dev_dp_query_cb = __soc_dev_dp_query_cb;

    TUYA_CALL_ERR_RETURN(tuya_iot_wf_soc_dev_init(GWCM_OLD, WF_START_AP_FIRST, &iot_cbs, PID, USER_SW_VER));

    TUYA_CALL_ERR_RETURN(tuya_iot_reg_get_wf_nw_stat_cb(__soc_dev_net_status_cb));

    TAL_PR_DEBUG("Youkai init led & key");

    /* Network button, LED initialization */
    app_led_init(LED_PIN);
    app_key_init(KEY_PIN);

    // TAL_PR_DEBUG("Youkai init light\n");

    // TUYA_CALL_ERR_RETURN(app_light_init());

    return 0;
}

STATIC VOID_T user_main(VOID_T)
{
    OPERATE_RET rt = OPRT_OK;

    /* Initialization, because DB initialization takes a long time, 
     * which affects the startup efficiency of some devices, 
     * so special processing is performed during initialization to delay initialization of DB
     */
    TY_INIT_PARAMS_S init_param = {0};
    init_param.init_db = TRUE;
    strcpy(init_param.sys_env, TARGET_PLATFORM);
    TUYA_CALL_ERR_LOG(tuya_iot_init_params(NULL, &init_param));

    tal_log_set_manage_attr(TAL_LOG_LEVEL_DEBUG);

    /* Initialization device */
    TAL_PR_DEBUG("device_init in");
    // TUYA_CALL_ERR_LOG(__soc_device_init());
    TUYA_CALL_ERR_LOG(app_light_init());

    return;
}

/**
* @brief  task thread
*
* @param[in] arg:Parameters when creating a task
* @return none
*/
STATIC VOID_T tuya_app_thread(VOID_T *arg)
{
    /* Initialization LWIP first!!! */
#if defined(ENABLE_LWIP) && (ENABLE_LWIP == 1)
    TUYA_LwIP_Init();
#endif

    user_main();

    tal_thread_delete(ty_app_thread);
    ty_app_thread = NULL;
}

/**
 * @brief user entry function
 *
 * @param[in] none: 
 *
 * @return none
 */
VOID_T tuya_app_main(VOID_T)
{
    THREAD_CFG_T thrd_param = {4096, 4, "tuya_app_main"};
    tal_thread_create_and_start(&ty_app_thread, NULL, NULL, tuya_app_thread, NULL, &thrd_param);
}

四、编译

在ubuntu下使用vscode进行编译很方便。
在这里插入图片描述

五、刷机

在这里插入图片描述

六、测试结果

如图,其中buf显示的是bh1750返回的值,两个字节。
比如01,38合起来就是0x138=312。

[01-01 00:43:20 TUYA E][tdd_sensor_bh1750.c:861] [BH1750] __tdd_sensor_bh1750_read
[01-01 00:43:20 TUYA E][tdd_sensor_bh1750.c:425] [BH1750] __bh1750_read_light
[01-01 00:43:20 TUYA E][tdd_sensor_bh1750.c:450] [BH1750] buf = 1 38 light= 312
[01-01 00:43:20 TUYA E][tdd_sensor_bh1750.c:871] [BH1750] get value. resl=2
[01-01 00:43:20 TUYA E][tdd_sensor_bh1750.c:392] light_val->sr_float=312.0
[01-01 00:43:20 TUYA I][app_light.c:147] Light: 312 sg_lt_dp_data.light.dp_value: 312
[01-01 00:43:22 TUYA E][tdd_sensor_bh1750.c:861] [BH1750] __tdd_sensor_bh1750_read
[01-01 00:43:22 TUYA E][tdd_sensor_bh1750.c:425] [BH1750] __bh1750_read_light
[01-01 00:43:22 TUYA E][tdd_sensor_bh1750.c:450] [BH1750] buf = 4 3d light= 1085
[01-01 00:43:22 TUYA E][tdd_sensor_bh1750.c:871] [BH1750] get value. resl=2
[01-01 00:43:22 TUYA E][tdd_sensor_bh1750.c:392] light_val->sr_float=1085.0
[01-01 00:43:22 TUYA I][app_light.c:147] Light: 1085 sg_lt_dp_data.light.dp_value: 312
[01-01 00:43:22 TUYA I][app_light.c:154] Light change. Enable report
[01-01 00:43:24 TUYA E][tdd_sensor_bh1750.c:861] [BH1750] __tdd_sensor_bh1750_read
[01-01 00:43:24 TUYA E][tdd_sensor_bh1750.c:425] [BH1750] __bh1750_read_light
[01-01 00:43:24 TUYA E][tdd_sensor_bh1750.c:450] [BH1750] buf = 4 3d light= 1085
[01-01 00:43:24 TUYA E][tdd_sensor_bh1750.c:871] [BH1750] get value. resl=2
[01-01 00:43:24 TUYA E][tdd_sensor_bh1750.c:392] light_val->sr_float=1085.0
[01-01 00:43:24 TUYA I][app_light.c:147] Light: 1085 sg_lt_dp_data.light.dp_value: 1085

在这里插入图片描述

小结

本章只是基础的添加驱动,后续还是需要实现联网并上传到云端。

补充一下,除了前期遇到环境搭建的网络问题,涂鸦的开发还是很舒服的,一键编译和一键下载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1275616.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于 ls -s 输出文件大小的单位问题的讨论

自己看书正好看到这里&#xff0c;正纳闷呢&#xff0c;上网查了下&#xff0c;发现不是我自己在为这个问题感到困惑。 有个大哥提出一个问题&#xff1a; 问题标题&#xff1a; ls -s的单位到底是什么&#xff1f; man ls -s, --size print the alloca…

库位角点检测之Centernet/CornerNet算法

1.CornerNet CornerNet 那么我们从bounding box左上角(top-left corner)看物体。视线横着的话&#xff0c;物体就在视线的下面&#xff08;那么视线所在位置为the topmost boundary of an object&#xff09;。视线竖着的话&#xff0c;物体就在视线的右边&#xff0c;那么视线…

CCFCSP试题编号:202009-2试题名称:风险人群筛查

#include <iostream> using namespace std;//判断是否在区域 bool isIn(int xl, int yd, int xr, int yu, int x, int y) {if ((x > xl && x < xr) && (y > yd && y < yu)){return true;}return false; }struct position {int a, b;…

【linux】日志有哪些

Linux系统日志主要有以下几种类型&#xff1a; 内核及系统日志&#xff1a;这种日志数据由系统服务rsyslog统一管理&#xff0c;根据其主配置文件/etc/rsyslog.conf中设置决定内核消息及各种系统程序消息记录到什么位置。/var/log/message&#xff1a;该日志文件存放了内核消息…

RDD2022提交官网得到F1-Score的步骤【自己摸索的,不保证对和全面,返回结果是F1-Score: India=nan】

文章目录 提交地址RDD2022提交的步骤1. 进入到官网2. 注册账号&登陆账号3. 提交界面4. 代码&#xff0c;制作符合要求的txt5. 提交后返回的结果 提交地址 RDD2022提交地址&#xff1a;https://crddc2022.sekilab.global/submissions/ RDD2020提交地址&#xff1a;https://…

nnDetection简明安装和训练流程(Windows环境)

安装 首先&#xff0c;官方不建议Windows安装&#xff0c;推荐Linux Docker 我的环境&#xff1a; ● 操作系统平台&#xff1a; Windows 10 ● Python&#xff1a; 3.8 ● Torch/TorchVision&#xff1a; 1.10.1cu102/ 0.11.1 ● GPU&#xff1a; Nvidia RTX 2080 Ti 11G…

【BEV感知 LSS方案】Lift-Splat-Shoot(LSS)

前言 LSS全称是Lift-Splat-Shoot&#xff0c;它先从车辆周围的多个摄像头拍摄到的图像进行特征提取&#xff0c;在特征图中估计出每个点的深度&#xff0c;然后把这些点“提升”到3D空间中。 接着&#xff0c;这些3D信息被放置到一个网格上&#xff0c;最后将这些信息“拍扁”…

转向更卷的奶茶 库迪这是要在咖啡上认怂?

卖咖啡刚满一年&#xff0c;陆正耀就带着名为“茶猫”的奶茶项目再度登场。 根据多位网友的爆料&#xff0c;茶猫采取和库迪咖啡一样的联营商模式&#xff0c;且有低价补贴策略&#xff0c;主打低价茶饮市场&#xff0c;全场统一定价6.9元。 熟悉的加盟模式&#xff0c;熟悉的…

国际上有哪些比较出名的VOIP供应商

1. Skype&#xff08;微软&#xff09;&#xff1a;企业发展历程&#xff1a;Skype 于2003年成立&#xff0c;最初由瑞典和丹麦的几位开发者创建。2005年被eBay收购&#xff0c;之后于2011年被微软收购。微软将 Skype 合并到其产品生态系统&#xff0c;并继续开发和改进该平…

性能测试JVM优化实战

&#xff08;1&#xff09;、实现高并发需要考虑的问题&#xff1a;12 条金字规则 实现高并发需要考虑&#xff1a; &#xff08;1&#xff09;系统的架构设计&#xff0c;如何在架构层面减少不必要的处理&#xff08;网络请求&#xff0c;数据库操作等&#xff09;--- 亿级流…

推荐一款优秀的json在线格式化校验工具

www.bjson.chat 这个工具是目前见过最好用的JSON工具&#xff0c; 页面简单&#xff0c;支持text&#xff0c;tree两种显示格式&#xff0c;关键词高亮显示支持亮白和暗黑两种风格最主要的是如果要格式化很长的json的话&#xff0c;这个工具还可以全屏显示&#xff0c;简直不…

真空环境试验箱中的精密低气压控制解决方案

摘要&#xff1a;针对用户提出的低气压试验箱中的真空度精密可编程控制&#xff0c;以及0.001~1000Torr的宽域真空度控制范围&#xff0c;本文基于动态平衡法提出了切实可行的解决方案。解决方案采用了上游控制和下游控制两路独立高精度的PID程序控制回路&#xff0c;基于不同量…

Python 批量修改文件名

主要步骤 通过os.listdir查看该文件夹下所有的文件&#xff08;包括文件夹&#xff09;遍历所有文件&#xff0c;如果是文件夹则跳过&#xff0c;或指定跳过指定文件获取文件扩展名按照需求生成新的文件路径文件名进行重命名 代码示例 # -*- coding: utf-8 -*- import osdef…

Python知识碎片补充【侯小啾python领航班系列(十四)】

Python知识碎片补充【侯小啾python领航班系列(十四)】 大家好,我是博主侯小啾, 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ�…

Adobe ColdFusion文件读取漏洞(CVE-2010-2861)

任务一&#xff1a; 复现漏洞 任务二&#xff1a; 尝试利用漏洞读取目标系统中的“opt/coldfusion8/license.txt"文件 1.环境搭建&#xff08;网上写的密码是admin&#xff0c;就用admin&#xff09; 2.看答案就是一层一层进行路径穿越攻击&#xff0c;这里要注意如果…

使用Docker Compose搭建CIG监控平台

CIG简介 CIG监控平台是基于CAdvisor、InfluxDB和Granfana构建的一个容器重量级监控系统&#xff0c;用于监控容器的各项性能指标。其中&#xff0c;CAdvisor是一个容器资源监控工具&#xff0c;用于监控容器的内存、CPU、网络IO和磁盘IO等。InfluxDB是一个开源的分布式时序、时…

【精选】VulnHub Shuriken-1 (超详细过程思路)

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

knn算法实现鸢尾花分类

KNN (K-Nearest Neighbors) 是一种监督学习算法&#xff0c;常用于分类和回归任务。下面是一个用Python和Scikit-learn库实现的鸢尾花分类的KNN算法示例&#xff1a; from sklearn import datasetsfrom sklearn.model_selection import train_test_splitfrom sklearn.preproce…

基于A*的网格地图最短路径问题求解

基于A*的网格地图最短路径问题求解 一、A*算法介绍、原理及步骤二、Dijkstra算法和A*的区别三、A*算法应用场景四、启发函数五、距离六、基于A*的网格地图最短路径问题求解实例分析完整代码 七、A*算法的改进思路 一、A*算法介绍、原理及步骤 A*搜索算法&#xff08;A star al…

指针(3)

如图&#xff0c;这是比较常见的冒泡排序&#xff0c;不过只能对整形数据进行排序。本篇博文主要介绍如何模拟qsort函数实现冒泡排序对任何数据的排序。 如果我们想对任何数据进行排序&#xff0c;我们可以发现&#xff0c;排序的趟数是固定的&#xff0c;我们只需要对比较大…