Last Updated on : 2024-11-20 02:14:53download
This topic lists all the API functions available for integration, and how to use them.
Download the code from GitHub.
When an error occurs during SDK runtime, an error code is returned to help you identify problems with the program. The error codes are stored in the /sdk/include/tuya_error_code.h
file under the tuya_iot_sdk
.
The logger is stored in the /sdk/include/uni_log.h
file under the tuya_iot_sdk
.
Log printing and log level setting are the two functions used in logging.
DEBUG
, the default log level, gives you the diagnostic information in a detailed manner but can lead to high memory usage. It is recommended to change the log level to NOTICE
for the release version.The following table lists all the functions for log printing:
Functional interfaces | Description |
---|---|
PR_ERR(fmt, ...) |
Records errors that occur at runtime. |
PR_WARN(fmt, ...) |
Records events that may lead to an error or require corrective action in the future. |
PR_NOTICE(fmt, ...) |
Records events that may be unusual but are not errors. |
PR_INFO(fmt, ...) |
Records information about normal behaviors of applications. |
PR_DEBUG(fmt, ...) |
Records debugging information. |
PR_TRACE(fmt, ...) |
Records code path execution. |
The following function is used to set the log level:
OPERATE_RET SetLogManageAttr(IN CONST LOG_LEVEL curLogLevel);
The higher you set the log level, the more information is printed. If you set the log level to TY_LOG_LEVEL_TRACE
, all the information is printed. If you set it to TY_LOG_LEVEL_NOTICE
, only NOTICE
, WARN
, and ERR
logs are printed.
Parameters:
curLogLevel
: The specified log level.
#define TY_LOG_LEVEL_ERR 0
#define TY_LOG_LEVEL_WARN 1
#define TY_LOG_LEVEL_NOTICE 2
#define TY_LOG_LEVEL_INFO 3
#define TY_LOG_LEVEL_DEBUG 4
#define TY_LOG_LEVEL_TRACE 5
Return:
OPRT_OK
: SuccessOthers
: FailureThe following figure shows that when we set the log level to TY_LOG_LEVEL_NOTICE
, only the PR_NOTICE
, PR_WARN
, and PR_ERR
logs are printed. When we set it to TY_LOG_LEVEL_DEBUG
, all logs except PR_TRACE
are printed.
Check out the complete code on GitHub.
void log_printf_demo(void)
{
PR_NOTICE("*************************************************");
SetLogManageAttr(TY_LOG_LEVEL_NOTICE);
PR_NOTICE("log level is NOTICE");
PR_ERR("This is error log");
PR_WARN("This is warn log");
PR_NOTICE("This is notice log");
PR_INFO("This is info log");
PR_DEBUG("This is debug log");
PR_TRACE("This is trace log");
PR_NOTICE("*************************************************");
SetLogManageAttr(TY_LOG_LEVEL_DEBUG);
PR_NOTICE("log level is DEBUG");
PR_ERR("This is error log");
PR_WARN("This is warn log");
PR_NOTICE("This is notice log");
PR_INFO("This is info log");
PR_DEBUG("This is debug log");
PR_TRACE("This is trace log");
PR_NOTICE("*************************************************");
}
The threads are stored in the /sdk/include/tuya_hal_thread.h
file under the tuya_iot_sdk
.
There are four thread functions:
tuya_hal_thread_create()
tuya_hal_thread_release()
tuya_hal_thread_is_self()
tuya_hal_thread_set_self_name()
int tuya_hal_thread_create(THREAD_HANDLE* thread,
const char* name,
uint32_t stack_size,
uint32_t priority,
THREAD_FUNC_T func,
void* const arg);
Create a thread.
Parameters:
thread
: an output parameter, indicating the handle to a thread.
name
: The name of a thread.
stack_size
: The stack size of a thread, in units of bits.
priority
: The priority of a thread.
/* The macro definition of priority is stored in `/sdk/include/uni_thread.h`. When you use it, make sure to add the header file `uni_thread.h`. */
#define TRD_PRIO_0 5 /* High */
#define TRD_PRIO_1 4
#define TRD_PRIO_2 3
#define TRD_PRIO_3 2
#define TRD_PRIO_4 1
#define TRD_PRIO_5 0
#define TRD_PRIO_6 0 /* low */
func
: The thread entry point.
arg
: The parameter of the thread entry point, which can be NULL
.
Return:
OPRT_OK
: SuccessOthers
: Failureint tuya_hal_thread_release(THREAD_HANDLE thread);
Release a thread.
Parameters:
thread
: The handle to a thread.Return:
OPRT_OK
: SuccessOthers
: Failureint tuya_hal_thread_is_self(THREAD_HANDLE thread, BOOL_T* is_self);
Determine whether the currently running thread is the calling thread
.
Parameters:
thread
: The handle to a thread.is_self
: an output parameter. If is_self == 1
, the currently running thread is the calling thread
. If is_self == 0
, the currently running thread is not the calling thread
.Return:
OPRT_OK
: SuccessOthers
: Failureint tuya_hal_thread_set_self_name(const char* name);
Rename a calling thread.
Parameters:
name
: The name to be set for a thread.Return:
OPRT_OK
: SuccessOthers
: FailureThe following code snippet creates a thread and releases it, which are the most commonly used functions.
In the example, we create a thread named thread demo
to print progress messages and thread count thread_demo_count
. When the count is greater than 10, the thread demo
is released and printing is terminated.
Check out the complete code on GitHub.
#include "uni_log.h"
#include "uni_thread.h"
#include "tuya_error_code.h"
#include "tuya_hal_system.h"
#include "thread_demo.h"
THREAD_HANDLE thread_demo_handle = NULL;
static thread_demo_count = 0;
void thread_demo_task_func(void)
{
OPERATE_RET op_ret = OPRT_OK;
for (;;) {
PR_NOTICE("thread demo is running, count: %d", thread_demo_count);
if (thread_demo_count >= 10) {
break;
}
thread_demo_count++;
tuya_hal_system_sleep(1000);
}
PR_NOTICE("thread demo task will release");
op_ret = tuya_hal_thread_release(thread_demo_handle);
if (OPRT_OK != op_ret) {
PR_ERR("release thread demo task failed, err_num:%d", op_ret);
return;
}
}
void thread_demo_init(void)
{
OPERATE_RET op_ret = OPRT_OK;
op_ret = tuya_hal_thread_create(&thread_demo_handle, "thread demo", 64*8, TRD_PRIO_4, thread_demo_task_func, NULL);
if (op_ret != OPRT_OK) {
PR_ERR("creat thread demo task failed, err_num:%d", op_ret);
return;
}
}
The software timer is stored in the /sdk/include/sys_timer.h
file under the tuya_iot_sdk
.
There are 12 software timer functions, which can be broken down into three parts:
The software timer initialization is performed when the SDK is initialized. Basically, you do not need to initialize and release the software timer again.
OPERATE_RET system_timer_init(void);
Initialize a software timer.
Parameters:
Return:
OPRT_OK
: SuccessOthers
: FailureOPERATE_RET system_timer_release(void);
Release the software timer, corresponding to system_timer_init
.
Parameters:
Return:
OPRT_OK
: SuccessOthers
: FailureOPERATE_RET sys_add_timer(IN CONST P_TIMER_FUNC pTimerFunc,\
IN CONST PVOID_T pTimerArg,\
OUT TIMER_ID *p_timerID);
Add a software timer.
Parameters:
pTimerFunc
: The callback.pTimerArg
: The parameter of the callback.p_timerID
: an output parameter, indicating the ID of a software timer.Return:
OPRT_OK
: SuccessOthers
: FailureOPERATE_RET sys_start_timer(IN CONST TIMER_ID timerID,\
IN CONST TIME_MS timeCycle,\
IN CONST TIMER_TYPE timer_type);
Start a software timer.
Parameters:
timerID
: The ID of a software timer.timeCycle
: The period of a timer, in milliseconds.timer_type
: The type of a software timer. TIMER_ONCE
indicates a one-time timer. TIMER_CYCLE
indicates a repeating timer.Return:
OPRT_OK
: SuccessOthers
: FailureOPERATE_RET sys_stop_timer(IN CONST TIMER_ID timerID);
Stop a timer. You can use sys_start_timer()
to start a stopped timer without adding a timer, but this can consume resources.
Parameters:
timerID
: The ID of a software timer.Return:
OPRT_OK
: SuccessOthers
: FailureOPERATE_RET sys_delete_timer(IN CONST TIMER_ID timerID);
Delete a timer. To start a deleted timer, you must use sys_add_timer()
to add a timer first.
Parameters:
timerID
: The ID of a software timer.Return:
OPRT_OK
: SuccessOthers
: FailureBOOL_T IsThisSysTimerRun(IN CONST TIMER_ID timer_id);
Determine the running status of a software timer.
Parameters:
timer_id
: The ID of a software timer.Return:
TRUE
: The timer is running.FAIL
: The timer is not running.The following functions are less used. Learn about them as needed.
OPERATE_RET sys_trigger_timer(IN CONST TIMER_ID timerID);
Trigger a timer immediately.
Parameters:
timerID
: The ID of a software timer.Return:
OPRT_OK
: SuccessOthers
: FailureINT_T sys_get_timer_num(void);
Get the number of active software timers, excluding those that are stopped or deleted.
Parameters:
Return:
ULONG_T system_timer_get_sleep_interval(VOID);
Get the minimum time interval of a timer.
Parameters:
Return:
VOID system_timer_set_sleep_interval(ULONG_T interval);
Set the minimum sleep interval of a timer.
Parameters:
interval
: The minimum sleep interval to be set.Return:
OPERATE_RET system_timer_cfg_stack_size(UINT_T stack_size);
Set the stack size of a software timer. Do not change the default size unless necessary.
Parameters:
stack_size
: The stack size to be set.Return:
OPRT_OK
: SuccessOthers
: FailureThe following code snippet adds and starts a software timer that would run 10 times and then stop.
Check out the complete code on GitHub.
#include "software_timer.h"
#include "uni_log.h"
#include "uni_thread.h"
#include "sys_timer.h"
TIMER_ID my_timer_id;
static int sw_run_count = 0;
void my_timer_cb(UINT_T timerID, PVOID_T pTimerArg)
{
OPERATE_RET op_ret = OPRT_OK;
PR_NOTICE("------this is timer %d callback, count: %d", timerID, sw_run_count);
sw_run_count++;
if (sw_run_count >= 10) {
if (IsThisSysTimerRun(my_timer_id)) {
op_ret = sys_stop_timer(my_timer_id);
if (OPRT_OK != op_ret) {
PR_ERR("sys stop timer failed, error code %d", op_ret);
return;
}
PR_NOTICE("timer %d is stop.", my_timer_id);
}
}
}
void sw_timer_task(void)
{
OPERATE_RET op_ret = OPRT_OK;
op_ret = sys_add_timer(my_timer_cb, NULL, &my_timer_id);
if (OPRT_OK != op_ret) {
PR_ERR("sys add timer failed, error code %d", op_ret);
return;
}
PR_NOTICE("timer add success, timer id: %d.", my_timer_id);
op_ret = sys_start_timer(my_timer_id, 2000, TIMER_CYCLE);
if (OPRT_OK != op_ret) {
PR_ERR("sys start timer failed, error code %d", op_ret);
return;
}
PR_NOTICE("timer %d start success.", my_timer_id);
}
The memory manager is stored in the /sdk/include/tuya_hal_memory.h
file under the tuya_iot_sdk
.
There are two memory management functions, which are used for memory allocation and release.
VOID_T *tuya_hal_system_malloc(CONST SIZE_T size);
Allocate memory resources.
Parameters:
size
: The requested stack size.Return:
NULL
: Memory allocation failed.Others
: Allocated memory address returned.VOID_T tuya_hal_system_free(VOID_T* ptr);
Release the allocated memory.
Parameters:
ptr
: The pointer to the memory to be released.Return:
NULL
The following code snippet requests three integer memory spaces, assigns values to the first two memory spaces, and prints the allocated memory addresses and the data stored in the allocated memory.
Check out the complete code on GitHub.
OPERATE_RET device_init(VOID)
{
int *str;
PR_NOTICE("******************** memory demo begin ********************");
str = tuya_hal_system_malloc(5*sizeof(int));
if (NULL == str) {
PR_ERR("tuya_hal_system_malloc is error");
return;
}
PR_NOTICE("memset");
memset(str, 0, 5*sizeof(int));
str[0] = 300;
str[1] = 200;
PR_NOTICE("str address: %x", str);
PR_NOTICE("str[0]:%d, str[1]:%d, str[2]:%d", str[0], str[1], str[2]);
if (NULL != str) {
PR_NOTICE("memory will free");
tuya_hal_system_free(str);
str = NULL;
PR_NOTICE("******************** memory demo end ********************");
}
return OPRT_OK;
}
The semaphore is stored in the /sdk/include/tuya_hal_semaphore.h
file under the tuya_iot_sdk
.
A semaphore is used to control access to a shared resource when a process is being executed.
INT_T tuya_hal_semaphore_create_init(SEM_HANDLE *pHandle, CONST UINT_T semCnt, CONST UINT_T sem_max);
Create and initialize a semaphore.
Parameters:
pHandle
: an output parameter, indicating the handle to a semaphore.semCnt
: The number of semaphores at the start.sem_max
: The maximum number of semaphores.Return:
OPRT_OK
: SuccessOthers
: FailureINT_T tuya_hal_semaphore_release(CONST SEM_HANDLE semHandle);
Release a semaphore, corresponding to tuya_hal_semaphore_create_init()
.
Parameters:
semHandle
: The handle to a semaphore to be released.Return:
OPRT_OK
: SuccessOthers
: FailureINT_T tuya_hal_semaphore_wait(CONST SEM_HANDLE semHandle);
Wait for a semaphore to be released. A wait
operation decrements the value of the semaphore by one. If the resulting semaphore value is zero, the calling thread or process is blocked, and cannot continue until some other thread or process increments it.
Parameters:
semHandle
: The handle to a semaphore.Return:
OPRT_OK
: SuccessOthers
: FailureINT_T tuya_hal_semaphore_waittimeout(CONST SEM_HANDLE semHandle, unsigned int timeout);
Wait for a semaphore to be released within a specified time period. A blocked function stops waiting for a semaphore when the specified timeout period expires.
Parameters:
semHandle
: The handle to a semaphore.timeout
: The timeout period.Return:
OPRT_OK
: SuccessOthers
: FailureINT_T tuya_hal_semaphore_post(CONST SEM_HANDLE semHandle);
A post
operation increments the value of the semaphore by one.
Parameters:
semHandle
: The handle to a semaphore.Return:
OPRT_OK
: SuccessOthers
: Failuretuya_hal_semaphore_create_init()
and tuya_hal_semaphore_release()
are used to create and release a semaphore respectively.
The following code snippet creates two tasks. One task creates a semaphore and posts it every five seconds. The other task waits for a semaphore and prints hello
on receiving the signal.
Check out the complete code on GitHub.
#include "sem.h"
#include "uni_log.h"
#include "uni_thread.h"
#include "tuya_hal_system.h"
#include "tuya_hal_semaphore.h"
SEM_HANDLE my_sem;
void sem_wait_task_handle(void)
{
for (;;) {
tuya_hal_semaphore_wait(my_sem);
PR_NOTICE("HELLO");
}
}
void sem_release_task_handle(void)
{
tuya_hal_semaphore_create_init(&my_sem, 0, 1);
for (;;) {
tuya_hal_semaphore_post(my_sem);
PR_NOTICE("sem is posted.");
tuya_hal_system_sleep(5000);
}
}
void sem_task_init(void)
{
tuya_hal_thread_create(NULL, "sem release", 64*8, TRD_PRIO_5, sem_release_task_handle, NULL);
tuya_hal_thread_create(NULL, "sem wait", 64*8, TRD_PRIO_5, sem_wait_task_handle, NULL);
}
The mutex is stored in the /sdk/include/tuya_hal_mutex.h
file under the tuya_iot_sdk
.
Mutex is a synchronization primitive that grants exclusive access to the shared resource to only one thread. Mutex is used to avoid race conditions between multiple threads.
OPERATE_RET tuya_hal_mutex_create_init(MUTEX_HANDLE *pMutexHandle);
Create and initialize a mutex.
Parameters:
pMutexHandle
: an output parameter, indicating the handle to a mutex.Return:
OPRT_OK
: SuccessOthers
: FailureOPERATE_RET tuya_hal_mutex_release(const MUTEX_HANDLE mutexHandle);
Release a mutex, corresponding to tuya_hal_mutex_create_init()
.
Parameters:
mutexHandle
: The handle to mutex.Return:
OPRT_OK
: SuccessOthers
: FailureOPERATE_RET tuya_hal_mutex_lock(const MUTEX_HANDLE mutexHandle);
Lock a mutex.
Parameters:
mutexHandle
: The handle to mutex.Return:
OPRT_OK
: SuccessOthers
: FailureOPERATE_RET tuya_hal_mutex_unlock(const MUTEX_HANDLE mutexHandle);
Unlock a mutex.
Parameters:
mutexHandle
: The handle to mutex.Return:
OPRT_OK
: SuccessOthers
: FailureCreate two tasks and use mutexes to ensure that only one task at a time accesses shared data.
Check out the complete code on GitHub.
#include "mutex.h"
#include "uni_log.h"
#include "tuya_hal_mutex.h"
#include "uni_thread.h"
#include "tuya_hal_system.h"
#include "tuya_hal_thread.h"
MUTEX_HANDLE my_mutex;
int demo_value = 0;
void task_1_handle(void)
{
for (;;) {
PR_NOTICE("task 1 wait unlock");
tuya_hal_mutex_lock(my_mutex);
PR_NOTICE("task 1 lock");
demo_value = demo_value + 2;
PR_NOTICE("task 1 demo value:%d", demo_value);
tuya_hal_system_sleep(3000);
tuya_hal_mutex_unlock(my_mutex);
PR_NOTICE("task 1 unlock");
tuya_hal_system_sleep(100);
}
}
void task_2_handle(void)
{
for (;;) {
PR_NOTICE("task 2 wait unlock");
tuya_hal_mutex_lock(my_mutex);
PR_NOTICE("task 2 lock");
demo_value--;
PR_NOTICE("task 2 demo value:%d", demo_value);
tuya_hal_system_sleep(5000);
tuya_hal_mutex_unlock(my_mutex);
PR_NOTICE("task 2 unlock");
tuya_hal_system_sleep(100);
}
}
void mutex_task_init(void)
{
tuya_hal_mutex_create_init(&my_mutex);
tuya_hal_thread_create(NULL, "task 1", 64*8, TRD_PRIO_5, task_1_handle, NULL);
tuya_hal_thread_create(NULL, "task 2", 64*8, TRD_PRIO_5, task_2_handle, NULL);
}
The following logs show that when the mutex is locked by task 2, task 1
waits for the mutex to be unlocked to proceed with its operations.
The queue is stored in the /sdk/include/uni_queue.h
file under the tuya_iot_sdk
.
When creating a queue, you need to set the maximum number of elements that can be stored in a queue and the length of a single element. The queue follows the first-in-first-out (FIFO) structure.
The queueing functions can be broken down into three parts:
P_QUEUE_CLASS CreateQueueObj(const unsigned int queTolNum, const unsigned int queUnitSize);
Create a queue.
Parameters:
queTolNum
: The maximum number of elements that can be stored in a queue.queUnitSize
: The length of a single element.Return:
NULL
: Queue creation failed.Others
: A queue is created, with the queue address returned.void ReleaseQueueObj(P_QUEUE_CLASS pQueObj);
Release a queue, corresponding to CreateQueueObj
.
Parameters:
pQueObj
: A queue to be released.Return:
NULL
unsigned char InQueue(P_QUEUE_CLASS pQueObj, const unsigned char *pQueUnit, const unsigned int queNum);
Add an element to a queue.
Parameters:
pQueObj
: The target queue.pQueUnit
: The first address of the element to be enqueued.queNum
: The number of elements to be enqueued.Return:
1
: SuccessOthers
: Failureunsigned char OutQueue(P_QUEUE_CLASS pQueObj,unsigned char *pQueUnit, const unsigned int queNum);
Remove an element from a queue.
Parameters:
pQueObj
: The target queue.pQueUnit
: The space address of the element to be dequeued.queNum
: The number of elements to be dequeued.Return:
1
: SuccessOthers
: Failureunsigned char GetQueueMember(P_QUEUE_CLASS pQueObj, const unsigned int start, unsigned char *pQueUnit, const unsigned int queNum);
Get the data stored in the queue. This function can be used to get the data of the specified length from anywhere in the queue without removing the data from the queue.
Parameters:
pQueObj
: A queue to be processed.start
: The specific element from which the retrieval starts. If you want to start from the first element, set this parameter to 1.pQueUnit
: The buffer address where the element is stored.queNum
: The number of elements to be obtained.Return:
1
: SuccessOthers
: Failureunsigned int GetCurQueNum(P_QUEUE_CLASS pQueObj);
Get the number of elements in the current queue.
Parameters:
pQueObj
: A queue to be processed.Return:
1
: SuccessOthers
: Failureunsigned int GetCurFreeQueNum(P_QUEUE_CLASS pQueObj);
Get the number of free elements in the current queue.
Parameters:
pQueObj
: A queue to be processed.Return:
1
: SuccessOthers
: Failureunsigned char DelQueueMember(P_QUEUE_CLASS pQueObj, const unsigned int queNum);
Remove the specified number of elements from a queue.
Parameters:
pQueObj
: A queue to be processed.queNum
: The number of elements to be removed.Return:
OPRT_OK
: SuccessOthers
: Failureunsigned char ClearQueue(P_QUEUE_CLASS pQueObj);
Empty a queue.
Parameters:
pQueObj
: A queue to be processed.Return:
OPRT_OK
: SuccessOthers
: FailureQueues are used for interprocess communication. In the example, all the available queueing features are demonstrated in one thread.
Create a queue with five elements and the size of a single element is an integer. Print the number of used and unused elements. Add eight digits to the queue and print the number of unused elements. Remove a digit from the queue and print its value and the number of remaining elements. Get the values of the first four elements and print them as well as the number of remaining elements. GetQueueMember()
does not change the remaining number of elements but OutQueue()
does. Remove an element from the queue, empty the queue, and finally release the queue.
Check out the complete code on GitHub.
#include "queue_demo.h"
#include "uni_log.h"
#include "tuya_hal_thread.h"
#include "uni_queue.h"
#include "uni_thread.h"
P_QUEUE_CLASS my_queue;
int in_number[] = {31, 32, 33, 5, 7};
int out_number[5];
void queue_task(void)
{
unsigned char ret;
int i;
/* create queue */
my_queue = CreateQueueObj(5, SIZEOF(int));
if (NULL == my_queue) {
PR_ERR("creat queue failed.");
return;
}
PR_NOTICE("create queue success.");
PR_NOTICE("cur queue num: %d", GetCurQueNum(my_queue));
PR_NOTICE("cur free num: %d", GetCurFreeQueNum(my_queue));
/* in queue */
ret = InQueue(my_queue, in_number, 5);
if (1 != ret) {
PR_ERR("in queue failed.");
} else {
PR_NOTICE("queue input 5 numbers success.");
}
PR_NOTICE("cur free num: %d", GetCurFreeQueNum(my_queue));
/* out queue */
ret = OutQueue(my_queue, out_number, 1);
if (1 != ret) {
PR_ERR("out queue failed.");
} else {
PR_NOTICE("queue out 1 number success.");
}
PR_NOTICE("out_number[0]: %d", out_number[0]);
PR_NOTICE("cur free num: %d", GetCurFreeQueNum(my_queue));
/* GetQueueMember */
ret = GetQueueMember(my_queue, 1, out_number, 4);
if (1 != ret) {
PR_ERR("queue get member failed.");
} else {
PR_NOTICE("GetQueueMember success.");
}
for (i=0; i<4; i++) {
PR_NOTICE("out_number[%d]:%d", i, out_number[i]);
}
PR_NOTICE("cur free num: %d", GetCurFreeQueNum(my_queue));
/* delete 1 queue number */
ret = DelQueueMember(my_queue, 1);
if (1 != ret) {
PR_ERR("delete queue number error.");
} else {
PR_NOTICE("delete queue number success.");
}
PR_NOTICE("cur free num: %d", GetCurFreeQueNum(my_queue));
/* clean queue */
ret = ClearQueue(my_queue);
if (1 != ret) {
PR_ERR("clean queue failed.");
} else {
PR_NOTICE("clean queue success.");
}
PR_NOTICE("cur free num: %d", GetCurFreeQueNum(my_queue));
/* release queue */
ReleaseQueueObj(my_queue);
PR_NOTICE("queue is release.");
}
Is this page helpful?
YesFeedbackIs this page helpful?
YesFeedback