forked from xuos/xiuos
				
			Merge pull request 'merge code to branch ok1052' (#6) from prepare_for_master into ok1052
ok
This commit is contained in:
		
						commit
						81f636cfe0
					
				| 
						 | 
				
			
			@ -10,3 +10,6 @@
 | 
			
		|||
[submodule "Ubiquitous/Nuttx/nuttx"]
 | 
			
		||||
	path = Ubiquitous/Nuttx/nuttx
 | 
			
		||||
	url = https://gitlink.org.cn/wgzAIIT/incubator-nuttx.git
 | 
			
		||||
[submodule "Ubiquitous/RT_Thread/aiit_board/aiit-riscv64-board/kendryte-sdk/kendryte-sdk-source"]
 | 
			
		||||
	path = Ubiquitous/RT_Thread/aiit_board/aiit-riscv64-board/kendryte-sdk/kendryte-sdk-source
 | 
			
		||||
	url = https://code.gitlink.org.cn/chunyexixiaoyu/kendryte-sdk-source.git
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,5 +18,5 @@ menu "Applications"
 | 
			
		|||
    source "$APP_DIR/Applications/control_app/Kconfig"
 | 
			
		||||
    source "$APP_DIR/Applications/knowing_app/Kconfig"
 | 
			
		||||
    source "$APP_DIR/Applications/sensor_app/Kconfig"
 | 
			
		||||
 | 
			
		||||
    source "$APP_DIR/Applications/embedded_database_app/Kconfig"
 | 
			
		||||
endmenu
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,5 +56,6 @@ void test_adc()
 | 
			
		|||
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
// SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
 | 
			
		||||
//                                                 test_adc, test_adc, read 3.3 voltage data from adc);
 | 
			
		||||
 | 
			
		||||
 SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
 | 
			
		||||
                                                 adc, test_adc, read 3.3 voltage data from adc);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@
 | 
			
		|||
* @author AIIT XUOS Lab
 | 
			
		||||
* @date 2021-05-29
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <transform.h>
 | 
			
		||||
#include <xizi.h>
 | 
			
		||||
#include "board.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -24,27 +25,13 @@
 | 
			
		|||
#include <lwip/sockets.h>
 | 
			
		||||
#include "lwip/sys.h"
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Definitions
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Prototypes
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Variables
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
#define TCP_DEMO_BUF_SIZE 65535
 | 
			
		||||
 | 
			
		||||
char tcp_socket_ip[] = {192, 168, 250, 252};
 | 
			
		||||
 | 
			
		||||
#define TCP_DEMO_BUF_SIZE 65535
 | 
			
		||||
/******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Code
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
static void tcp_recv_demo(void *arg)
 | 
			
		||||
static void TCPSocketRecvTask(void *arg)
 | 
			
		||||
{
 | 
			
		||||
    int fd = -1, clientfd;
 | 
			
		||||
    int recv_len;
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +67,7 @@ static void tcp_recv_demo(void *arg)
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        lw_print("tcp bind success, start to receive.\n");
 | 
			
		||||
        lw_print("\n\nLocal Port:%d\n\n", LWIP_LOCAL_PORT);
 | 
			
		||||
        lw_pr_info("\n\nLocal Port:%d\n\n", LWIP_LOCAL_PORT);
 | 
			
		||||
 | 
			
		||||
        // setup socket fd as listening mode
 | 
			
		||||
        if (listen(fd, 5) != 0 )
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +78,7 @@ static void tcp_recv_demo(void *arg)
 | 
			
		|||
 | 
			
		||||
        // accept client connection
 | 
			
		||||
        clientfd = accept(fd, (struct sockaddr *)&tcp_addr, (socklen_t*)&addr_len);
 | 
			
		||||
        lw_print("client %s connected\n", inet_ntoa(tcp_addr.sin_addr));
 | 
			
		||||
        lw_pr_info("client %s connected\n", inet_ntoa(tcp_addr.sin_addr));
 | 
			
		||||
 | 
			
		||||
        while(1)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +101,7 @@ static void tcp_recv_demo(void *arg)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tcp_socket_recv_run(int argc, char *argv[])
 | 
			
		||||
void TCPSocketRecvTest(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
    int result = 0;
 | 
			
		||||
    pthread_t th_id;
 | 
			
		||||
| 
						 | 
				
			
			@ -126,15 +113,14 @@ void tcp_socket_recv_run(int argc, char *argv[])
 | 
			
		|||
        sscanf(argv[1], "%d.%d.%d.%d", &tcp_socket_ip[0], &tcp_socket_ip[1], &tcp_socket_ip[2], &tcp_socket_ip[3]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ETH_BSP_Config();
 | 
			
		||||
    lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
 | 
			
		||||
    sys_thread_new("tcp_recv_demo", tcp_recv_demo, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
 | 
			
		||||
    sys_thread_new("TCPSocketRecvTask", TCPSocketRecvTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
 | 
			
		||||
     TCPSocketRecv, tcp_socket_recv_run, TCP recv echo);
 | 
			
		||||
     TCPSocketRecv, TCPSocketRecvTest, TCP recv echo);
 | 
			
		||||
 | 
			
		||||
static void tcp_send_demo(void *arg)
 | 
			
		||||
static void TCPSocketSendTask(void *arg)
 | 
			
		||||
{
 | 
			
		||||
    int cnt = LWIP_DEMO_TIMES;
 | 
			
		||||
    int fd = -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +149,7 @@ static void tcp_send_demo(void *arg)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    lw_print("tcp connect success, start to send.\n");
 | 
			
		||||
    lw_pr_info("\n\nTarget Port:%d\n\n", tcp_sock.sin_port);
 | 
			
		||||
    lw_pr_info("\n\nTarget Port:%d\n\n", LWIP_TARGET_PORT);
 | 
			
		||||
 | 
			
		||||
    while (cnt --)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -182,7 +168,7 @@ __exit:
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void tcp_socket_send_run(int argc, char *argv[])
 | 
			
		||||
void TCPSocketSendTest(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
    if(argc == 2)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -190,11 +176,10 @@ void tcp_socket_send_run(int argc, char *argv[])
 | 
			
		|||
        sscanf(argv[1], "%d.%d.%d.%d", &tcp_socket_ip[0], &tcp_socket_ip[1], &tcp_socket_ip[2], &tcp_socket_ip[3]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ETH_BSP_Config();
 | 
			
		||||
    lwip_config_tcp(lwip_ipaddr, lwip_netmask, tcp_socket_ip);
 | 
			
		||||
    sys_thread_new("tcp socket", tcp_send_demo, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
 | 
			
		||||
    sys_thread_new("tcp socket", TCPSocketSendTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
 | 
			
		||||
     TCPSocketSend, tcp_socket_send_run, TCP send demo);
 | 
			
		||||
     TCPSocketSend, TCPSocketSendTest, TCP send demo);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,36 +23,20 @@
 | 
			
		|||
#include "sys_arch.h"
 | 
			
		||||
#include "lwip/udp.h"
 | 
			
		||||
#include "lwip/opt.h"
 | 
			
		||||
#include <lwip/sockets.h>
 | 
			
		||||
#include "lwip/sys.h"
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Definitions
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
#define UDP_BUF_SIZE 65536
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Prototypes
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Variables
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
extern char udp_target[];
 | 
			
		||||
static struct udp_pcb *udpecho_raw_pcb;
 | 
			
		||||
char udp_socket_ip[] = {192, 168, 250, 252};
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Code
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
/******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <lwip/sockets.h>
 | 
			
		||||
#include "lwip/sys.h"
 | 
			
		||||
 | 
			
		||||
#define LWIP_UDP_TASK_STACK 4096
 | 
			
		||||
#define LWIP_UDP_TASK_PRIO 25
 | 
			
		||||
#define UDP_BUF_SIZE 1024
 | 
			
		||||
 | 
			
		||||
static void udp_recv_demo(void *arg)
 | 
			
		||||
static void UdpSocketRecvTask(void *arg)
 | 
			
		||||
{
 | 
			
		||||
    lw_print("udp_recv_demo start.\n");
 | 
			
		||||
    lw_print("UdpSocketRecvTask start.\n");
 | 
			
		||||
 | 
			
		||||
    int socket_fd = -1;
 | 
			
		||||
    char *recv_buf;
 | 
			
		||||
| 
						 | 
				
			
			@ -63,14 +47,14 @@ static void udp_recv_demo(void *arg)
 | 
			
		|||
    while(1)
 | 
			
		||||
    {
 | 
			
		||||
        recv_buf = (char *)malloc(UDP_BUF_SIZE);
 | 
			
		||||
        if (recv_buf == NULL)
 | 
			
		||||
        if(recv_buf == NULL)
 | 
			
		||||
        {
 | 
			
		||||
            lw_print("No memory\n");
 | 
			
		||||
            goto __exit;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
 | 
			
		||||
        if (socket_fd < 0)
 | 
			
		||||
        if(socket_fd < 0)
 | 
			
		||||
        {
 | 
			
		||||
            lw_print("Socket error\n");
 | 
			
		||||
            goto __exit;
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +65,7 @@ static void udp_recv_demo(void *arg)
 | 
			
		|||
        udp_addr.sin_port = htons(LWIP_LOCAL_PORT);
 | 
			
		||||
        memset(&(udp_addr.sin_zero), 0, sizeof(udp_addr.sin_zero));
 | 
			
		||||
 | 
			
		||||
        if (bind(socket_fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1)
 | 
			
		||||
        if(bind(socket_fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1)
 | 
			
		||||
        {
 | 
			
		||||
            lw_print("Unable to bind\n");
 | 
			
		||||
            goto __exit;
 | 
			
		||||
| 
						 | 
				
			
			@ -94,28 +78,25 @@ static void udp_recv_demo(void *arg)
 | 
			
		|||
        {
 | 
			
		||||
            memset(recv_buf, 0, UDP_BUF_SIZE);
 | 
			
		||||
            recv_len = recvfrom(socket_fd, recv_buf, UDP_BUF_SIZE, 0, (struct sockaddr *)&server_addr, &addr_len);
 | 
			
		||||
            lw_print("Receive from : %s\n", inet_ntoa(server_addr.sin_addr));
 | 
			
		||||
            lw_print("Receive data : %s\n\n", recv_buf);
 | 
			
		||||
            lw_pr_info("Receive from : %s\n", inet_ntoa(server_addr.sin_addr));
 | 
			
		||||
            lw_pr_info("Receive data : %s\n\n", recv_buf);
 | 
			
		||||
            sendto(socket_fd, recv_buf, recv_len, 0, (struct sockaddr*)&server_addr, addr_len);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    __exit:
 | 
			
		||||
        if (socket_fd >= 0)
 | 
			
		||||
        if(socket_fd >= 0)
 | 
			
		||||
        {
 | 
			
		||||
            closesocket(socket_fd);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (recv_buf)
 | 
			
		||||
        if(recv_buf)
 | 
			
		||||
        {
 | 
			
		||||
            free(recv_buf);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void udp_recv_demo_thread(void* param)
 | 
			
		||||
{
 | 
			
		||||
    ETH_BSP_Config();
 | 
			
		||||
    lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
 | 
			
		||||
    sys_thread_new("udp_recv_demo", udp_recv_demo, NULL, LWIP_UDP_TASK_STACK, LWIP_UDP_TASK_PRIO);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void udp_socket_recv_run(int argc, char *argv[])
 | 
			
		||||
void UdpSocketRecvTask(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
    int result = 0;
 | 
			
		||||
    pthread_t th_id;
 | 
			
		||||
| 
						 | 
				
			
			@ -127,24 +108,25 @@ void udp_socket_recv_run(int argc, char *argv[])
 | 
			
		|||
        sscanf(argv[1], "%d.%d.%d.%d", &udp_socket_ip[0], &udp_socket_ip[1], &udp_socket_ip[2], &udp_socket_ip[3]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sys_thread_new("udp socket send", udp_recv_demo_thread, NULL, 4096, 15);
 | 
			
		||||
    lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
 | 
			
		||||
    sys_thread_new("UdpSocketRecvTask", UdpSocketRecvTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
 | 
			
		||||
     UDPSocketRecv, udp_socket_recv_run, UDP recv echo);
 | 
			
		||||
     UDPSocketRecv, UdpSocketRecvTask, UDP recv echo);
 | 
			
		||||
 | 
			
		||||
static void udp_send_demo(void *arg)
 | 
			
		||||
static void UdpSocketSendTask(void *arg)
 | 
			
		||||
{
 | 
			
		||||
    int cnt = LWIP_DEMO_TIMES;
 | 
			
		||||
    char send_str[128];
 | 
			
		||||
 | 
			
		||||
    lw_print("udp_send_demo start.\n");
 | 
			
		||||
    lw_print("UdpSocketSendTask start.\n");
 | 
			
		||||
 | 
			
		||||
    int socket_fd = -1;
 | 
			
		||||
    memset(send_str, 0, sizeof(send_str));
 | 
			
		||||
 | 
			
		||||
    socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
 | 
			
		||||
    if (socket_fd < 0)
 | 
			
		||||
    if(socket_fd < 0)
 | 
			
		||||
    {
 | 
			
		||||
        lw_print("Socket error\n");
 | 
			
		||||
        goto __exit;
 | 
			
		||||
| 
						 | 
				
			
			@ -153,10 +135,10 @@ static void udp_send_demo(void *arg)
 | 
			
		|||
    struct sockaddr_in udp_sock;
 | 
			
		||||
    udp_sock.sin_family = AF_INET;
 | 
			
		||||
    udp_sock.sin_port = htons(LWIP_TARGET_PORT);
 | 
			
		||||
    udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(udp_target[0],udp_target[1],udp_target[2],udp_target[3]));
 | 
			
		||||
    udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(udp_target[0], udp_target[1], udp_target[2], udp_target[3]));
 | 
			
		||||
    memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero));
 | 
			
		||||
 | 
			
		||||
    if (connect(socket_fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr)))
 | 
			
		||||
    if(connect(socket_fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr)))
 | 
			
		||||
    {
 | 
			
		||||
        lw_print("Unable to connect\n");
 | 
			
		||||
        goto __exit;
 | 
			
		||||
| 
						 | 
				
			
			@ -174,7 +156,7 @@ static void udp_send_demo(void *arg)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
__exit:
 | 
			
		||||
    if (socket_fd >= 0)
 | 
			
		||||
    if(socket_fd >= 0)
 | 
			
		||||
    {
 | 
			
		||||
        closesocket(socket_fd);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -182,14 +164,7 @@ __exit:
 | 
			
		|||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void udp_send_demo_thread(void* param)
 | 
			
		||||
{
 | 
			
		||||
    ETH_BSP_Config();
 | 
			
		||||
    lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
 | 
			
		||||
    sys_thread_new("udp_send_demo", udp_send_demo, NULL, LWIP_UDP_TASK_STACK, LWIP_UDP_TASK_PRIO);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void udp_socket_send_run(int argc, char *argv[])
 | 
			
		||||
void UdpSocketSendTest(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
    int result = 0;
 | 
			
		||||
    pthread_t th_id;
 | 
			
		||||
| 
						 | 
				
			
			@ -201,9 +176,10 @@ void udp_socket_send_run(int argc, char *argv[])
 | 
			
		|||
        sscanf(argv[1], "%d.%d.%d.%d", &udp_socket_ip[0], &udp_socket_ip[1], &udp_socket_ip[2], &udp_socket_ip[3]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sys_thread_new("udp socket send", udp_send_demo_thread, NULL, 4096, 15);
 | 
			
		||||
    lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
 | 
			
		||||
    sys_thread_new("UdpSocketSendTask", UdpSocketSendTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
 | 
			
		||||
     UDPSocketSend, udp_socket_send_run, UDP send echo);
 | 
			
		||||
     UDPSocketSend, UdpSocketSendTest, UDP send echo);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@ SRC_DIR :=
 | 
			
		|||
ifeq ($(CONFIG_RESOURCES_LWIP),y)
 | 
			
		||||
 | 
			
		||||
ifeq ($(CONFIG_USING_CONTROL_PLC_OPCUA), y)
 | 
			
		||||
	SRC_DIR += opcua_demo
 | 
			
		||||
	SRC_DIR += opcua_demo plc_demo
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,9 @@
 | 
			
		|||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#define TCP_LOCAL_PORT 4840
 | 
			
		||||
#define UA_URL_SIZE 100
 | 
			
		||||
#define UA_URL_SIZE    100
 | 
			
		||||
#define UA_STACK_SIZE  4096
 | 
			
		||||
#define UA_TASK_PRIO   15
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Prototypes
 | 
			
		||||
| 
						 | 
				
			
			@ -40,80 +42,71 @@
 | 
			
		|||
 * Variables
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
char test_ua_ip[] = {192, 168, 250, 5};
 | 
			
		||||
char test_ua_ip[] = {192, 168, 250, 2};
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Code
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
static void test_ua_connect(void *arg)
 | 
			
		||||
static void UaConnectTestTask(void* arg)
 | 
			
		||||
{
 | 
			
		||||
    struct netif net;
 | 
			
		||||
    UA_StatusCode retval;
 | 
			
		||||
    char ua_uri[UA_URL_SIZE];
 | 
			
		||||
 | 
			
		||||
    memset(ua_uri, 0, sizeof(ua_uri));
 | 
			
		||||
    UA_Client* client = UA_Client_new();
 | 
			
		||||
 | 
			
		||||
    UA_Client *client = UA_Client_new();
 | 
			
		||||
 | 
			
		||||
    if (client == NULL)
 | 
			
		||||
    if(client == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("ua: [%s] tcp client null\n", __func__);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UA_ClientConfig *config = UA_Client_getConfig(client);
 | 
			
		||||
    UA_ClientConfig* config = UA_Client_getConfig(client);
 | 
			
		||||
    UA_ClientConfig_setDefault(config);
 | 
			
		||||
    snprintf(ua_uri, sizeof(ua_uri), "opc.tcp://%d.%d.%d.%d:4840",
 | 
			
		||||
             test_ua_ip[0], test_ua_ip[1], test_ua_ip[2], test_ua_ip[3]);
 | 
			
		||||
    ua_pr_info("ua uri: %d %s\n", strlen(ua_uri), ua_uri);
 | 
			
		||||
    retval = UA_Client_connect(client,ua_uri);
 | 
			
		||||
 | 
			
		||||
    snprintf(ua_uri, UA_URL_SIZE, "opc.tcp://%d.%d.%d.%d:4840",
 | 
			
		||||
        test_ua_ip[0], test_ua_ip[1], test_ua_ip[2], test_ua_ip[3]);
 | 
			
		||||
 | 
			
		||||
    retval = UA_Client_connect(client, ua_uri);
 | 
			
		||||
    if (retval != UA_STATUSCODE_GOOD)
 | 
			
		||||
    if(retval != UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("ua: [%s] ret %x\n", __func__, retval);
 | 
			
		||||
        ua_pr_info("ua: [%s] connected failed %x\n", __func__, retval);
 | 
			
		||||
        UA_Client_delete(client);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ua_print("ua: [%s] start Ua Test!\n", __func__);
 | 
			
		||||
    ua_pr_info("ua: [%s] connected ok!\n", __func__);
 | 
			
		||||
    UA_Client_disconnect(client);
 | 
			
		||||
    UA_Client_delete(client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_ua_connect_thr(void *arg)
 | 
			
		||||
void UaConnectTest(void* arg)
 | 
			
		||||
{
 | 
			
		||||
    ETH_BSP_Config();
 | 
			
		||||
    lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip);
 | 
			
		||||
    test_ua_connect(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_sh_ua_connect(void)
 | 
			
		||||
{
 | 
			
		||||
    int result = 0;
 | 
			
		||||
    pthread_t th_id;
 | 
			
		||||
    pthread_attr_t attr;
 | 
			
		||||
    sys_thread_new("ua test", test_ua_connect_thr, NULL, 4096, 15);
 | 
			
		||||
    sys_thread_new("ua test", UaConnectTestTask, NULL, UA_STACK_SIZE, UA_TASK_PRIO);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
 | 
			
		||||
                 UaConnect, test_sh_ua_connect, Test Opc UA connection);
 | 
			
		||||
                 UaConnect, UaConnectTest, Test Opc UA connection);
 | 
			
		||||
 | 
			
		||||
void test_ua_browser_objects(void *param)
 | 
			
		||||
void UaBrowserObjectsTestTask(void* param)
 | 
			
		||||
{
 | 
			
		||||
    UA_Client *client = UA_Client_new();
 | 
			
		||||
 | 
			
		||||
    UA_Client* client = UA_Client_new();
 | 
			
		||||
    ua_pr_info("ua: [%s] start ...\n", __func__);
 | 
			
		||||
 | 
			
		||||
    if (client == NULL)
 | 
			
		||||
    if(client == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("ua: [%s] tcp client null\n", __func__);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UA_ClientConfig *config = UA_Client_getConfig(client);
 | 
			
		||||
    UA_ClientConfig* config = UA_Client_getConfig(client);
 | 
			
		||||
    UA_ClientConfig_setDefault(config);
 | 
			
		||||
    UA_StatusCode retval = UA_Client_connect(client, opc_server_url);
 | 
			
		||||
 | 
			
		||||
    UA_StatusCode retval = UA_Client_connect(client, OPC_SERVER);
 | 
			
		||||
    if(retval != UA_STATUSCODE_GOOD) {
 | 
			
		||||
    if(retval != UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("ua: [%s] connect failed %#x\n", __func__, retval);
 | 
			
		||||
        UA_Client_delete(client);
 | 
			
		||||
        return;
 | 
			
		||||
| 
						 | 
				
			
			@ -121,18 +114,15 @@ void test_ua_browser_objects(void *param)
 | 
			
		|||
 | 
			
		||||
    ua_print("ua: [%s] connect ok!\n", __func__);
 | 
			
		||||
    ua_pr_info("--- start read time ---\n", __func__);
 | 
			
		||||
 | 
			
		||||
    ua_read_time(client);
 | 
			
		||||
 | 
			
		||||
    ua_pr_info("--- get server info ---\n", __func__);
 | 
			
		||||
    ua_browser_objects(client);
 | 
			
		||||
 | 
			
		||||
    ua_test_browser_objects(client);
 | 
			
		||||
    /* Clean up */
 | 
			
		||||
    UA_Client_disconnect(client);
 | 
			
		||||
    UA_Client_delete(client); /* Disconnects the client internally */
 | 
			
		||||
    UA_Client_delete(client);    /* Disconnects the client internally */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *test_sh_ua_brower_objects(int argc, char *argv[])
 | 
			
		||||
void* UaBrowserObjectsTest(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    if(argc == 2)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -146,47 +136,45 @@ void *test_sh_ua_brower_objects(int argc, char *argv[])
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ETH_BSP_Config();
 | 
			
		||||
    lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip);
 | 
			
		||||
    sys_thread_new("ua object", test_ua_browser_objects, NULL, 4096, 15);
 | 
			
		||||
    sys_thread_new("ua object", UaBrowserObjectsTestTask, NULL, UA_STACK_SIZE, UA_TASK_PRIO);
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
 | 
			
		||||
                 UaObj, test_sh_ua_brower_objects, UaObj [IP]);
 | 
			
		||||
                 UaObj, UaBrowserObjectsTest, UaObj [IP]);
 | 
			
		||||
 | 
			
		||||
void test_ua_get_info(void *param)
 | 
			
		||||
void UaGetInfoTestTask(void* param)
 | 
			
		||||
{
 | 
			
		||||
    UA_Client *client = UA_Client_new();
 | 
			
		||||
 | 
			
		||||
    UA_Client* client = UA_Client_new();
 | 
			
		||||
    ua_pr_info("ua: [%s] start ...\n", __func__);
 | 
			
		||||
 | 
			
		||||
    if (client == NULL)
 | 
			
		||||
    if(client == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("ua: [%s] tcp client null\n", __func__);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UA_ClientConfig *config = UA_Client_getConfig(client);
 | 
			
		||||
    UA_ClientConfig* config = UA_Client_getConfig(client);
 | 
			
		||||
    UA_ClientConfig_setDefault(config);
 | 
			
		||||
    UA_StatusCode retval = UA_Client_connect(client, opc_server_url);
 | 
			
		||||
 | 
			
		||||
    UA_StatusCode retval = UA_Client_connect(client, OPC_SERVER);
 | 
			
		||||
    if(retval != UA_STATUSCODE_GOOD) {
 | 
			
		||||
    if(retval != UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("ua: [%s] connect failed %#x\n", __func__, retval);
 | 
			
		||||
        UA_Client_delete(client);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ua_print("ua: [%s] connect ok!\n", __func__);
 | 
			
		||||
    ua_pr_info("--- get server info ---\n", __func__);
 | 
			
		||||
    ua_get_server_info(client);
 | 
			
		||||
 | 
			
		||||
    ua_pr_info("--- interactive server ---\n", __func__);
 | 
			
		||||
    ua_test_interact_server(client);
 | 
			
		||||
    /* Clean up */
 | 
			
		||||
    UA_Client_disconnect(client);
 | 
			
		||||
    UA_Client_delete(client); /* Disconnects the client internally */
 | 
			
		||||
    UA_Client_delete(client);    /* Disconnects the client internally */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *test_sh_ua_get_info(int argc, char *argv[])
 | 
			
		||||
void* UaGetInfoTest(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    if(argc == 2)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -200,12 +188,63 @@ void *test_sh_ua_get_info(int argc, char *argv[])
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ETH_BSP_Config();
 | 
			
		||||
    lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip);
 | 
			
		||||
    sys_thread_new("ua object", test_ua_browser_objects, NULL, 4096, 15);
 | 
			
		||||
    sys_thread_new("ua info", UaGetInfoTestTask, NULL, UA_STACK_SIZE, UA_TASK_PRIO);
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
 | 
			
		||||
                 UaInfo, test_sh_ua_get_info, UaInfo [IP]);
 | 
			
		||||
                 UaInfo, UaGetInfoTest, UaInfo [IP]);
 | 
			
		||||
 | 
			
		||||
void UaAddNodesTask(void* param)
 | 
			
		||||
{
 | 
			
		||||
    UA_Client* client = UA_Client_new();
 | 
			
		||||
    ua_pr_info("ua: [%s] start ...\n", __func__);
 | 
			
		||||
 | 
			
		||||
    if(client == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("ua: [%s] tcp client null\n", __func__);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UA_ClientConfig* config = UA_Client_getConfig(client);
 | 
			
		||||
    UA_ClientConfig_setDefault(config);
 | 
			
		||||
    UA_StatusCode retval = UA_Client_connect(client, opc_server_url);
 | 
			
		||||
 | 
			
		||||
    if(retval != UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("ua: [%s] connect failed %#x\n", __func__, retval);
 | 
			
		||||
        UA_Client_delete(client);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ua_print("ua: [%s] connect ok!\n", __func__);
 | 
			
		||||
    ua_pr_info("--- add nodes ---\n", __func__);
 | 
			
		||||
    ua_add_nodes(client);
 | 
			
		||||
    /* Clean up */
 | 
			
		||||
    UA_Client_disconnect(client);
 | 
			
		||||
    UA_Client_delete(client);    /* Disconnects the client internally */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* UaAddNodesTest(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    if(argc == 2)
 | 
			
		||||
    {
 | 
			
		||||
        if(isdigit(argv[1][0]))
 | 
			
		||||
        {
 | 
			
		||||
            if(sscanf(argv[1], "%d.%d.%d.%d", &test_ua_ip[0], &test_ua_ip[1], &test_ua_ip[2], &test_ua_ip[3]) == EOF)
 | 
			
		||||
            {
 | 
			
		||||
                lw_pr_info("input wrong ip\n");
 | 
			
		||||
                return NULL;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip);
 | 
			
		||||
    sys_thread_new("ua add nodes", UaAddNodesTask, NULL, UA_STACK_SIZE, UA_TASK_PRIO);
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
 | 
			
		||||
                 UaAdd, UaAddNodesTest, UA Add Nodes);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
SRC_FILES := plc_show_demo.c plc_control_demo.c
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,221 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2022 AIIT XUOS Lab
 | 
			
		||||
 * XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
 *        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PSL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file plc_control_demo.c
 | 
			
		||||
 * @brief Demo for PLC control
 | 
			
		||||
 * @version 1.0
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2022.2.22
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "transform.h"
 | 
			
		||||
#include "open62541.h"
 | 
			
		||||
#include "ua_api.h"
 | 
			
		||||
#include "sys_arch.h"
 | 
			
		||||
#include "plc_demo.h"
 | 
			
		||||
 | 
			
		||||
#define PLC_NS_FORMAT "n%d,%s"
 | 
			
		||||
 | 
			
		||||
struct PlcChannel plc_demo_ch;
 | 
			
		||||
struct PlcDriver plc_demo_drv;
 | 
			
		||||
struct PlcDevice plc_demo_dev;
 | 
			
		||||
 | 
			
		||||
PlcCtrlParamType plc_ctrl_param;
 | 
			
		||||
 | 
			
		||||
UA_NodeId test_nodeid = {4, UA_NODEIDTYPE_NUMERIC, 5};
 | 
			
		||||
 | 
			
		||||
/******************************************************************************/
 | 
			
		||||
 | 
			
		||||
void PlcDemoChannelDrvInit(void)
 | 
			
		||||
{
 | 
			
		||||
    static uint8_t init_flag = 0;
 | 
			
		||||
    if(init_flag)
 | 
			
		||||
        return;
 | 
			
		||||
    init_flag = 1;
 | 
			
		||||
 | 
			
		||||
    lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip);
 | 
			
		||||
    PlcChannelInit(&plc_demo_ch, PLC_CH_NAME);
 | 
			
		||||
    if(PlcDriverInit(&plc_demo_drv, PLC_DRV_NAME) == EOK)
 | 
			
		||||
    {
 | 
			
		||||
        PlcDriverAttachToChannel(PLC_DRV_NAME, PLC_CH_NAME);
 | 
			
		||||
    }
 | 
			
		||||
    memset(&plc_demo_dev, 0, sizeof(plc_demo_dev));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void PlcCtrlDemoInit(void)
 | 
			
		||||
{
 | 
			
		||||
    static uint8_t init_flag = 0;
 | 
			
		||||
 | 
			
		||||
    PlcDemoChannelDrvInit();
 | 
			
		||||
    // register plc device
 | 
			
		||||
    plc_demo_dev.state = CHDEV_INIT;
 | 
			
		||||
    strcpy(plc_demo_dev.name, "UA Demo");
 | 
			
		||||
    plc_demo_dev.info.product = "CPU 1215C";
 | 
			
		||||
    plc_demo_dev.info.vendor = "SIEMENS";
 | 
			
		||||
    plc_demo_dev.info.model = "S7-1200";
 | 
			
		||||
    plc_demo_dev.info.id = 123;
 | 
			
		||||
    plc_demo_dev.net = PLC_IND_ENET_OPCUA;
 | 
			
		||||
 | 
			
		||||
    // register UA parameter
 | 
			
		||||
    if(!plc_demo_dev.priv_data)
 | 
			
		||||
    {
 | 
			
		||||
        plc_demo_dev.priv_data = (UaParamType*)malloc(sizeof(UaParamType));
 | 
			
		||||
    }
 | 
			
		||||
    UaParamType* ua_ptr = plc_demo_dev.priv_data;
 | 
			
		||||
    memset(ua_ptr, 0, sizeof(UaParamType));
 | 
			
		||||
    strcpy(ua_ptr->ua_remote_ip, opc_server_url);
 | 
			
		||||
    ua_ptr->act = UA_ACT_ATTR;
 | 
			
		||||
    memcpy(&ua_ptr->ua_id, &test_nodeid, sizeof(test_nodeid));
 | 
			
		||||
 | 
			
		||||
    if(init_flag)
 | 
			
		||||
        return;
 | 
			
		||||
    init_flag = 1;
 | 
			
		||||
 | 
			
		||||
    if(PlcDevRegister(&plc_demo_dev, NULL, plc_demo_dev.name) != EOK)
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    PlcDeviceAttachToChannel(plc_demo_dev.name, PLC_CH_NAME);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PlcReadUATask(void* arg)
 | 
			
		||||
{
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
    struct PlcOps* ops = NULL;
 | 
			
		||||
    char buf[PLC_BUF_SIZE];
 | 
			
		||||
    memset(buf, 0, sizeof(buf));
 | 
			
		||||
    PlcCtrlDemoInit();
 | 
			
		||||
    ops = plc_demo_dev.ops;
 | 
			
		||||
    ret = ops->open(&plc_demo_dev);
 | 
			
		||||
 | 
			
		||||
    if(EOK != ret)
 | 
			
		||||
    {
 | 
			
		||||
        plc_print("plc: [%s] open failed %#x\n", __func__, ret);
 | 
			
		||||
//        free(plc_demo_dev.priv_data);
 | 
			
		||||
//        plc_demo_dev.priv_data = NULL;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = ops->read(&plc_demo_dev, buf, PLC_BUF_SIZE);
 | 
			
		||||
 | 
			
		||||
    if(EOK != ret)
 | 
			
		||||
    {
 | 
			
		||||
        plc_print("plc: [%s] read failed %x\n", __func__, ret);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ops->close(&plc_demo_dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PlcReadTest(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    static char node_str[UA_NODE_LEN];
 | 
			
		||||
    memset(node_str, 0, sizeof(node_str));
 | 
			
		||||
 | 
			
		||||
    if(argc > 1)
 | 
			
		||||
    {
 | 
			
		||||
        plc_print("plc: arg %s\n", argv[1]);
 | 
			
		||||
 | 
			
		||||
        if(sscanf(argv[1], PLC_NS_FORMAT, &test_nodeid.namespaceIndex, node_str) != EOF)
 | 
			
		||||
        {
 | 
			
		||||
            if(isdigit(node_str[0]))
 | 
			
		||||
            {
 | 
			
		||||
                test_nodeid.identifierType = UA_NODEIDTYPE_NUMERIC;
 | 
			
		||||
                test_nodeid.identifier.numeric = atoi(node_str);
 | 
			
		||||
                plc_print("ns %d num %d\n", test_nodeid.namespaceIndex, test_nodeid.identifier.numeric);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                test_nodeid.identifierType = UA_NODEIDTYPE_STRING;
 | 
			
		||||
                test_nodeid.identifier.string.length = strlen(node_str);
 | 
			
		||||
                test_nodeid.identifier.string.data = node_str;
 | 
			
		||||
                plc_print("ns %d str %s\n", test_nodeid.namespaceIndex, test_nodeid.identifier.string.data);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sys_thread_new("plc read", PlcReadUATask, NULL, PLC_STACK_SIZE, PLC_TASK_PRIO);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
 | 
			
		||||
                 PlcRead, PlcReadTest, Read PLC);
 | 
			
		||||
 | 
			
		||||
void PlcWriteUATask(void* arg)
 | 
			
		||||
{
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
    struct PlcOps* ops = NULL;
 | 
			
		||||
    char buf[PLC_BUF_SIZE];
 | 
			
		||||
    memset(buf, 0, sizeof(buf));
 | 
			
		||||
 | 
			
		||||
    PlcCtrlDemoInit();
 | 
			
		||||
    ops = plc_demo_dev.ops;
 | 
			
		||||
    ret = ops->open(&plc_demo_dev);
 | 
			
		||||
 | 
			
		||||
    if(EOK != ret)
 | 
			
		||||
    {
 | 
			
		||||
        plc_print("plc: [%s] open failed %#x\n", __func__, ret);
 | 
			
		||||
//        free(plc_demo_dev.priv_data);
 | 
			
		||||
//        plc_demo_dev.priv_data = NULL;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = ops->write(&plc_demo_dev, arg, PLC_BUF_SIZE);
 | 
			
		||||
 | 
			
		||||
    if(EOK != ret)
 | 
			
		||||
    {
 | 
			
		||||
        plc_print("plc: [%s] read failed\n", __func__);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ops->close(&plc_demo_dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PlcWriteTest(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    static char node_str[UA_NODE_LEN];
 | 
			
		||||
    static char val_param[UA_NODE_LEN];
 | 
			
		||||
    memset(node_str, 0, sizeof(node_str));
 | 
			
		||||
    memset(val_param, 0, sizeof(val_param));
 | 
			
		||||
 | 
			
		||||
    if(argc > 1)
 | 
			
		||||
    {
 | 
			
		||||
        plc_print("plc: arg %s\n", argv[1]);
 | 
			
		||||
 | 
			
		||||
        if(sscanf(argv[1], PLC_NS_FORMAT, &test_nodeid.namespaceIndex, node_str) != EOF)
 | 
			
		||||
        {
 | 
			
		||||
            if(isdigit(node_str[0]))
 | 
			
		||||
            {
 | 
			
		||||
                test_nodeid.identifierType = UA_NODEIDTYPE_NUMERIC;
 | 
			
		||||
                test_nodeid.identifier.numeric = atoi(node_str);
 | 
			
		||||
                plc_print("ns %d num %d\n", test_nodeid.namespaceIndex, test_nodeid.identifier.numeric);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                test_nodeid.identifierType = UA_NODEIDTYPE_STRING;
 | 
			
		||||
                test_nodeid.identifier.string.length = strlen(node_str);
 | 
			
		||||
                test_nodeid.identifier.string.data = node_str;
 | 
			
		||||
                plc_print("ns %d str %s\n", test_nodeid.namespaceIndex, test_nodeid.identifier.string.data);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(argc > 2)
 | 
			
		||||
        {
 | 
			
		||||
            strcpy(val_param, argv[2]);
 | 
			
		||||
            plc_print("write value %s\n", val_param);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sys_thread_new("plc write", PlcWriteUATask, val_param, PLC_STACK_SIZE, PLC_TASK_PRIO);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
 | 
			
		||||
                 PlcWrite, PlcWriteTest, Read PLC);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2022 AIIT XUOS Lab
 | 
			
		||||
 * XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
 *        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PSL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file plc_show_demo.c
 | 
			
		||||
 * @brief Demo for PLC information show
 | 
			
		||||
 * @version 1.0
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2022.02.24
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __PLC_DEMO_H_
 | 
			
		||||
#define __PLC_DEMO_H_
 | 
			
		||||
 | 
			
		||||
#include "plc_channel.h"
 | 
			
		||||
#include "plc_device.h"
 | 
			
		||||
 | 
			
		||||
#define PLC_CH_NAME "PLC"
 | 
			
		||||
#define PLC_DRV_NAME "OPCUA"
 | 
			
		||||
 | 
			
		||||
#define PLC_BUF_SIZE 128
 | 
			
		||||
 | 
			
		||||
#define PLC_STACK_SIZE  4096
 | 
			
		||||
#define PLC_TASK_PRIO   15
 | 
			
		||||
 | 
			
		||||
extern struct PlcChannel plc_demo_ch;
 | 
			
		||||
extern struct PlcDriver plc_demo_drv;
 | 
			
		||||
extern struct PlcDevice plc_demo_dev;
 | 
			
		||||
 | 
			
		||||
void PlcDemoChannelDrvInit(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,257 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2022 AIIT XUOS Lab
 | 
			
		||||
 * XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
 *        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PSL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file plc_show_demo.c
 | 
			
		||||
 * @brief Demo for PLC information show
 | 
			
		||||
 * @version 1.0
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2022.02.24
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "transform.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
 | 
			
		||||
#include "open62541.h"
 | 
			
		||||
#include "ua_api.h"
 | 
			
		||||
#include "sys_arch.h"
 | 
			
		||||
#include "plc_demo.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define PLC_DEMO_NUM 5
 | 
			
		||||
 | 
			
		||||
struct PlcDevice plc_demo_array[PLC_DEMO_NUM];
 | 
			
		||||
 | 
			
		||||
typedef struct PlcShowParam
 | 
			
		||||
{
 | 
			
		||||
    int id;
 | 
			
		||||
    char* vector;
 | 
			
		||||
    char* model;
 | 
			
		||||
    char* product;
 | 
			
		||||
} PlcShowParamType;
 | 
			
		||||
 | 
			
		||||
PlcShowParamType plc_demo_param[PLC_NAME_SIZE] =
 | 
			
		||||
{
 | 
			
		||||
    {1, "SIEMENS", "S7-1500", "CPU 1512SP-1PN"},
 | 
			
		||||
    {2, "SIEMENS", "S7-1200", "CPU 1215C"},
 | 
			
		||||
    {3, "SIEMSNS", "S7-200", "CPU SR60"},
 | 
			
		||||
    {4, "B&R", "X20", "X20 CP1586"},
 | 
			
		||||
    {5, "B&R", "X20", "X20 CP1381"}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static char* const channel_type_str[] =
 | 
			
		||||
{
 | 
			
		||||
    "PLC_Channel",
 | 
			
		||||
    "Unknown"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern DoublelistType plcdev_list;
 | 
			
		||||
extern DoublelistType ch_linklist;
 | 
			
		||||
 | 
			
		||||
/**********************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
void PlcShowTitle(const char* item_array[])
 | 
			
		||||
{
 | 
			
		||||
    int i = 0, max_len = 65;
 | 
			
		||||
    KPrintf(" %-15s%-15s%-15s%-15s%-20s\n", item_array[0], item_array[1], item_array[2], item_array[3], item_array[4]);
 | 
			
		||||
 | 
			
		||||
    while(i < max_len)
 | 
			
		||||
    {
 | 
			
		||||
        i++;
 | 
			
		||||
 | 
			
		||||
        if(max_len == i)
 | 
			
		||||
        {
 | 
			
		||||
            KPrintf("-\n");
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            KPrintf("-");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ChDrvType ShowChannelFindDriver(struct Channel* ch)
 | 
			
		||||
{
 | 
			
		||||
    struct ChDrv* driver = NONE;
 | 
			
		||||
    DoublelistType* node = NONE;
 | 
			
		||||
    DoublelistType* head = &ch->ch_drvlink;
 | 
			
		||||
 | 
			
		||||
    for(node = head->node_next; node != head; node = node->node_next)
 | 
			
		||||
    {
 | 
			
		||||
        driver = DOUBLE_LIST_ENTRY(node, struct ChDrv, driver_link);
 | 
			
		||||
        return driver;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void PlcShowDemoInit(void)
 | 
			
		||||
{
 | 
			
		||||
    static uint8_t init_flag = 0;
 | 
			
		||||
    int i;
 | 
			
		||||
    PlcDemoChannelDrvInit();
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < PLC_DEMO_NUM; i++)
 | 
			
		||||
    {
 | 
			
		||||
        // register plc device
 | 
			
		||||
        plc_demo_array[i].state = CHDEV_INIT;
 | 
			
		||||
        snprintf(plc_demo_array[i].name, PLC_NAME_SIZE, "PLC Demo %d", i);
 | 
			
		||||
        plc_demo_array[i].info.vendor = plc_demo_param[i].vector;
 | 
			
		||||
        plc_demo_array[i].info.model = plc_demo_param[i].model;
 | 
			
		||||
        plc_demo_array[i].info.id = plc_demo_param[i].id;
 | 
			
		||||
        plc_demo_array[i].info.product = plc_demo_param[i].product;
 | 
			
		||||
        plc_demo_array[i].net = PLC_IND_ENET_OPCUA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(init_flag)
 | 
			
		||||
        return;
 | 
			
		||||
    init_flag = 1;
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < PLC_DEMO_NUM; i++)
 | 
			
		||||
    {
 | 
			
		||||
        if(PlcDevRegister(&plc_demo_array[i], NULL, plc_demo_array[i].name) == EOK)
 | 
			
		||||
        {
 | 
			
		||||
            PlcDeviceAttachToChannel(plc_demo_array[i].name, PLC_CH_NAME);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PlcShowChannel(void)
 | 
			
		||||
{
 | 
			
		||||
    ChannelType ch;
 | 
			
		||||
    ChDrvType driver;
 | 
			
		||||
    ChDevType device;
 | 
			
		||||
    int dev_cnt;
 | 
			
		||||
    DoublelistType* ch_node = NONE;
 | 
			
		||||
    DoublelistType* ch_head = &ch_linklist;
 | 
			
		||||
    const char* item_array[] = {"ch_type", "ch_name", "drv_name", "dev_name", "cnt"};
 | 
			
		||||
    PlcShowDemoInit();
 | 
			
		||||
    PlcShowTitle(item_array);
 | 
			
		||||
    ch_node = ch_head->node_next;
 | 
			
		||||
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
        ch = DOUBLE_LIST_ENTRY(ch_node, struct Channel, ch_link);
 | 
			
		||||
 | 
			
		||||
        if((ch) && (ch->ch_type == CH_PLC_TYPE))
 | 
			
		||||
        {
 | 
			
		||||
            KPrintf("%s", " ");
 | 
			
		||||
            KPrintf("%-15s%-15s",
 | 
			
		||||
                    channel_type_str[ch->ch_type],
 | 
			
		||||
                    ch->ch_name);
 | 
			
		||||
 | 
			
		||||
            driver = ShowChannelFindDriver(ch);
 | 
			
		||||
 | 
			
		||||
            if(driver)
 | 
			
		||||
            {
 | 
			
		||||
                KPrintf("%-15s", driver->drv_name);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                KPrintf("%-15s", "nil");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(ch->haldev_cnt)
 | 
			
		||||
            {
 | 
			
		||||
                DoublelistType* dev_node = NONE;
 | 
			
		||||
                DoublelistType* dev_head = &ch->ch_devlink;
 | 
			
		||||
                dev_node = dev_head->node_next;
 | 
			
		||||
                dev_cnt = 1;
 | 
			
		||||
 | 
			
		||||
                while(dev_node != dev_head)
 | 
			
		||||
                {
 | 
			
		||||
                    device = DOUBLE_LIST_ENTRY(dev_node, struct ChDev, dev_link);
 | 
			
		||||
 | 
			
		||||
                    if(1 == dev_cnt)
 | 
			
		||||
                    {
 | 
			
		||||
                        if(device)
 | 
			
		||||
                        {
 | 
			
		||||
                            KPrintf("%-16s%-4d\n", device->dev_name, dev_cnt);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            KPrintf("%-16s%-4d\n", "nil", dev_cnt);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        KPrintf("%46s", " ");
 | 
			
		||||
 | 
			
		||||
                        if(device)
 | 
			
		||||
                        {
 | 
			
		||||
                            KPrintf("%-16s%-4d\n", device->dev_name, dev_cnt);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            KPrintf("%-16s%-4d\n", "nil", dev_cnt);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    dev_cnt++;
 | 
			
		||||
                    dev_node = dev_node->node_next;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                KPrintf("\n");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ch_node = ch_node->node_next;
 | 
			
		||||
    }
 | 
			
		||||
    while(ch_node != ch_head);
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
 | 
			
		||||
                 ShowChannel, PlcShowChannel, Show PLC information);
 | 
			
		||||
 | 
			
		||||
void PlcShowDev(void)
 | 
			
		||||
{
 | 
			
		||||
    PlcDeviceType* plc_dev;
 | 
			
		||||
    ChDrvType driver;
 | 
			
		||||
    ChDevType device;
 | 
			
		||||
    DoublelistType* plc_node = NONE;
 | 
			
		||||
    DoublelistType* plc_head = &plcdev_list;
 | 
			
		||||
    const char* item_array[] = {"device", "vendor", "model", "product", "id"};
 | 
			
		||||
    PlcShowDemoInit();
 | 
			
		||||
    PlcShowTitle(item_array);
 | 
			
		||||
    plc_node = plc_head->node_next;
 | 
			
		||||
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
        plc_dev = DOUBLE_LIST_ENTRY(plc_node, struct PlcDevice, link);
 | 
			
		||||
 | 
			
		||||
        if(plc_dev)
 | 
			
		||||
        {
 | 
			
		||||
            KPrintf("%s", " ");
 | 
			
		||||
            KPrintf("%-15s%-15s%-15s%-15s%-20d",
 | 
			
		||||
                    plc_dev->name,
 | 
			
		||||
                    plc_dev->info.vendor,
 | 
			
		||||
                    plc_dev->info.model,
 | 
			
		||||
                    plc_dev->info.product,
 | 
			
		||||
                    plc_dev->info.id);
 | 
			
		||||
            KPrintf("\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        plc_node = plc_node->node_next;
 | 
			
		||||
    }
 | 
			
		||||
    while(plc_node != plc_head);
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
 | 
			
		||||
                 ShowPlc, PlcShowDev, Show PLC information);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
menuconfig USING_EMBEDDED_DATABASE_APP
 | 
			
		||||
    bool "embedded database app"
 | 
			
		||||
    default n
 | 
			
		||||
if USING_EMBEDDED_DATABASE_APP
 | 
			
		||||
        source "$APP_DIR/Applications/embedded_database_app/flashdb_app/Kconfig" 
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
import os
 | 
			
		||||
Import('RTT_ROOT')
 | 
			
		||||
from building import *
 | 
			
		||||
 | 
			
		||||
cwd = GetCurrentDir()
 | 
			
		||||
objs = []
 | 
			
		||||
list = os.listdir(cwd)
 | 
			
		||||
 | 
			
		||||
for d in list:
 | 
			
		||||
    path = os.path.join(cwd, d)
 | 
			
		||||
    if os.path.isfile(os.path.join(path, 'SConscript')):
 | 
			
		||||
        objs = objs + SConscript(os.path.join(path, 'SConscript'))
 | 
			
		||||
 | 
			
		||||
Return('objs')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
config EMBEDDED_DATABASE_FLASHDB_APP
 | 
			
		||||
    bool "embedded database apps/flashdb(example)"
 | 
			
		||||
    select USING_EMBEDDED_DATABASE
 | 
			
		||||
    select USING_EMBEDDED_DATABASE_FLASHDB
 | 
			
		||||
    default n
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
from building import *
 | 
			
		||||
 | 
			
		||||
cwd     = GetCurrentDir()
 | 
			
		||||
src     = Glob('*.c') + Glob('*.cpp')
 | 
			
		||||
CPPPATH = [cwd]
 | 
			
		||||
 | 
			
		||||
group = DefineGroup('flashdb(example)', src, depend = ['EMBEDDED_DATABASE_FLASHDB_APP'], LOCAL_CPPPATH = CPPPATH)
 | 
			
		||||
 | 
			
		||||
Return('group')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,129 @@
 | 
			
		|||
#include <transform.h>
 | 
			
		||||
#include <flashdb.h>
 | 
			
		||||
#define FDB_LOG_TAG "[flashdb_app]"
 | 
			
		||||
static pthread_mutex_t kv_locker, ts_locker;
 | 
			
		||||
static uint32_t boot_count = 0;
 | 
			
		||||
static time_t boot_time[10] = {0, 1, 2, 3};
 | 
			
		||||
/* default KV nodes */
 | 
			
		||||
static struct fdb_default_kv_node default_kv_table[] = {
 | 
			
		||||
        {"username", "armink", 0}, /* string KV */
 | 
			
		||||
        {"password", "123456", 0}, /* string KV */
 | 
			
		||||
        {"boot_count", &boot_count, sizeof(boot_count)}, /* int type KV */
 | 
			
		||||
        {"boot_time", &boot_time, sizeof(boot_time)},    /* int array type KV */
 | 
			
		||||
};
 | 
			
		||||
/* KVDB object */
 | 
			
		||||
static struct fdb_kvdb kvdb = { 0 };
 | 
			
		||||
/* TSDB object */
 | 
			
		||||
struct fdb_tsdb tsdb = { 0 };
 | 
			
		||||
/* counts for simulated timestamp */
 | 
			
		||||
static int counts = 0;
 | 
			
		||||
 | 
			
		||||
extern void kvdb_basic_sample(fdb_kvdb_t kvdb);
 | 
			
		||||
extern void kvdb_type_string_sample(fdb_kvdb_t kvdb);
 | 
			
		||||
extern void kvdb_type_blob_sample(fdb_kvdb_t kvdb);
 | 
			
		||||
extern void tsdb_sample(fdb_tsdb_t tsdb);
 | 
			
		||||
 | 
			
		||||
static void lock(fdb_db_t db)
 | 
			
		||||
{
 | 
			
		||||
    pthread_mutex_lock((pthread_mutex_t *)db->user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void unlock(fdb_db_t db)
 | 
			
		||||
{
 | 
			
		||||
    pthread_mutex_unlock((pthread_mutex_t *)db->user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static fdb_time_t get_time(void)
 | 
			
		||||
{
 | 
			
		||||
    return time(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int flashdb_app(void)
 | 
			
		||||
{
 | 
			
		||||
    fdb_err_t result;
 | 
			
		||||
    bool file_mode = true;
 | 
			
		||||
    uint32_t sec_size = 4096, db_size = sec_size * 4;
 | 
			
		||||
 | 
			
		||||
#ifdef FDB_USING_KVDB
 | 
			
		||||
    { /* KVDB Sample */
 | 
			
		||||
        struct fdb_default_kv default_kv;
 | 
			
		||||
 | 
			
		||||
        default_kv.kvs = default_kv_table;
 | 
			
		||||
        default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]);
 | 
			
		||||
        /* set the lock and unlock function if you want */
 | 
			
		||||
        pthread_mutex_init(&kv_locker, NULL);
 | 
			
		||||
        fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_LOCK, (void *)lock);
 | 
			
		||||
        fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_UNLOCK, (void *)unlock);
 | 
			
		||||
        /* set the sector and database max size */
 | 
			
		||||
        fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_SEC_SIZE, &sec_size);
 | 
			
		||||
        fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_MAX_SIZE, &db_size);
 | 
			
		||||
        /* enable file mode */
 | 
			
		||||
        fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_FILE_MODE, &file_mode);
 | 
			
		||||
        /* create database directory */
 | 
			
		||||
        mkdir("fdb_kvdb1", 0777);
 | 
			
		||||
        /* Key-Value database initialization
 | 
			
		||||
         *
 | 
			
		||||
         *       &kvdb: database object
 | 
			
		||||
         *       "env": database name
 | 
			
		||||
         * "fdb_kvdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
 | 
			
		||||
         *              Please change to YOUR partition name.
 | 
			
		||||
         * &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully.
 | 
			
		||||
         *  &kv_locker: The locker object.
 | 
			
		||||
         */
 | 
			
		||||
        result = fdb_kvdb_init(&kvdb, "env", "fdb_kvdb1", &default_kv, &kv_locker);
 | 
			
		||||
 | 
			
		||||
        if (result != FDB_NO_ERR) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* run basic KV samples */
 | 
			
		||||
        kvdb_basic_sample(&kvdb);
 | 
			
		||||
        /* run string KV samples */
 | 
			
		||||
        kvdb_type_string_sample(&kvdb);
 | 
			
		||||
        /* run blob KV samples */
 | 
			
		||||
        kvdb_type_blob_sample(&kvdb);
 | 
			
		||||
    }
 | 
			
		||||
#endif /* FDB_USING_KVDB */
 | 
			
		||||
 | 
			
		||||
#ifdef FDB_USING_TSDB
 | 
			
		||||
    { /* TSDB Sample */
 | 
			
		||||
        /* set the lock and unlock function if you want */
 | 
			
		||||
        pthread_mutex_init(&ts_locker, NULL);
 | 
			
		||||
        fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_LOCK, (void *)lock);
 | 
			
		||||
        fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_UNLOCK, (void *)unlock);
 | 
			
		||||
        /* set the sector and database max size */
 | 
			
		||||
        fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_SEC_SIZE, &sec_size);
 | 
			
		||||
        fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_MAX_SIZE, &db_size);
 | 
			
		||||
        /* enable file mode */
 | 
			
		||||
        fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_FILE_MODE, &file_mode);
 | 
			
		||||
        /* create database directory */
 | 
			
		||||
        mkdir("fdb_tsdb1", 0777);
 | 
			
		||||
        /* Time series database initialization
 | 
			
		||||
         *
 | 
			
		||||
         *       &tsdb: database object
 | 
			
		||||
         *       "log": database name
 | 
			
		||||
         * "fdb_tsdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
 | 
			
		||||
         *              Please change to YOUR partition name.
 | 
			
		||||
         *    get_time: The get current timestamp function.
 | 
			
		||||
         *         128: maximum length of each log
 | 
			
		||||
         *   ts_locker: The locker object.
 | 
			
		||||
         */
 | 
			
		||||
        result = fdb_tsdb_init(&tsdb, "log", "fdb_tsdb1", get_time, 128, &ts_locker);
 | 
			
		||||
        /* read last saved time for simulated timestamp */
 | 
			
		||||
        fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_GET_LAST_TIME, &counts);
 | 
			
		||||
 | 
			
		||||
        if (result != FDB_NO_ERR) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* run TSDB sample */
 | 
			
		||||
        tsdb_sample(&tsdb);
 | 
			
		||||
    }
 | 
			
		||||
#endif /* FDB_USING_TSDB */
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __RT_THREAD_H__
 | 
			
		||||
MSH_CMD_EXPORT(flashdb_app, flashdb test);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * @brief basic KV samples.
 | 
			
		||||
 *
 | 
			
		||||
 * basic Key-Value Database KV feature samples
 | 
			
		||||
 * get and show currnet boot counts
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <flashdb.h>
 | 
			
		||||
 | 
			
		||||
#ifdef FDB_USING_KVDB
 | 
			
		||||
 | 
			
		||||
#define FDB_LOG_TAG "[sample][kvdb][basic]"
 | 
			
		||||
 | 
			
		||||
void kvdb_basic_sample(fdb_kvdb_t kvdb)
 | 
			
		||||
{
 | 
			
		||||
    struct fdb_blob blob;
 | 
			
		||||
    int boot_count = 0;
 | 
			
		||||
 | 
			
		||||
    FDB_INFO("==================== kvdb_basic_sample ====================\n");
 | 
			
		||||
 | 
			
		||||
    { /* GET the KV value */
 | 
			
		||||
        /* get the "boot_count" KV value */
 | 
			
		||||
        fdb_kv_get_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count)));
 | 
			
		||||
        /* the blob.saved.len is more than 0 when get the value successful */
 | 
			
		||||
        if (blob.saved.len > 0) {
 | 
			
		||||
            FDB_INFO("get the 'boot_count' value is %d\n", boot_count);
 | 
			
		||||
        } else {
 | 
			
		||||
            FDB_INFO("get the 'boot_count' failed\n");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    { /* CHANGE the KV value */
 | 
			
		||||
        /* increase the boot count */
 | 
			
		||||
        boot_count ++;
 | 
			
		||||
        /* change the "boot_count" KV's value */
 | 
			
		||||
        fdb_kv_set_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count)));
 | 
			
		||||
        FDB_INFO("set the 'boot_count' value to %d\n", boot_count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FDB_INFO("===========================================================\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* FDB_USING_KVDB */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * @brief blob KV samples.
 | 
			
		||||
 *
 | 
			
		||||
 * Key-Value Database blob type KV feature samples
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <flashdb.h>
 | 
			
		||||
 | 
			
		||||
#ifdef FDB_USING_KVDB
 | 
			
		||||
 | 
			
		||||
#define FDB_LOG_TAG "[sample][kvdb][blob]"
 | 
			
		||||
 | 
			
		||||
void kvdb_type_blob_sample(fdb_kvdb_t kvdb)
 | 
			
		||||
{
 | 
			
		||||
    struct fdb_blob blob;
 | 
			
		||||
 | 
			
		||||
    FDB_INFO("==================== kvdb_type_blob_sample ====================\n");
 | 
			
		||||
 | 
			
		||||
    { /* CREATE new Key-Value */
 | 
			
		||||
        int temp_data = 36;
 | 
			
		||||
 | 
			
		||||
        /* It will create new KV node when "temp" KV not in database.
 | 
			
		||||
         * fdb_blob_make: It's a blob make function, and it will return the blob when make finish.
 | 
			
		||||
         */
 | 
			
		||||
        fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
 | 
			
		||||
        FDB_INFO("create the 'temp' blob KV, value is: %d\n", temp_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    { /* GET the KV value */
 | 
			
		||||
        int temp_data = 0;
 | 
			
		||||
 | 
			
		||||
        /* get the "temp" KV value */
 | 
			
		||||
        fdb_kv_get_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
 | 
			
		||||
        /* the blob.saved.len is more than 0 when get the value successful */
 | 
			
		||||
        if (blob.saved.len > 0) {
 | 
			
		||||
            FDB_INFO("get the 'temp' value is: %d\n", temp_data);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    { /* CHANGE the KV value */
 | 
			
		||||
        int temp_data = 38;
 | 
			
		||||
 | 
			
		||||
        /* change the "temp" KV's value to 38 */
 | 
			
		||||
        fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
 | 
			
		||||
        FDB_INFO("set 'temp' value to %d\n", temp_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    { /* DELETE the KV by name */
 | 
			
		||||
        fdb_kv_del(kvdb, "temp");
 | 
			
		||||
        FDB_INFO("delete the 'temp' finish\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FDB_INFO("===========================================================\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* FDB_USING_KVDB */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * @brief string KV samples.
 | 
			
		||||
 *
 | 
			
		||||
 * Key-Value Database string type KV feature samples source file.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <flashdb.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#ifdef FDB_USING_KVDB
 | 
			
		||||
 | 
			
		||||
#define FDB_LOG_TAG "[sample][kvdb][string]"
 | 
			
		||||
 | 
			
		||||
void kvdb_type_string_sample(fdb_kvdb_t kvdb)
 | 
			
		||||
{
 | 
			
		||||
    FDB_INFO("==================== kvdb_type_string_sample ====================\n");
 | 
			
		||||
 | 
			
		||||
    { /* CREATE new Key-Value */
 | 
			
		||||
        char temp_data[10] = "36C";
 | 
			
		||||
 | 
			
		||||
        /* It will create new KV node when "temp" KV not in database. */
 | 
			
		||||
        fdb_kv_set(kvdb, "temp", temp_data);
 | 
			
		||||
        FDB_INFO("create the 'temp' string KV, value is: %s\n", temp_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    { /* GET the KV value */
 | 
			
		||||
        char *return_value, temp_data[10] = { 0 };
 | 
			
		||||
 | 
			
		||||
        /* Get the "temp" KV value.
 | 
			
		||||
         * NOTE: The return value saved in fdb_kv_get's buffer. Please copy away as soon as possible.
 | 
			
		||||
         */
 | 
			
		||||
        return_value = fdb_kv_get(kvdb, "temp");
 | 
			
		||||
        /* the return value is NULL when get the value failed */
 | 
			
		||||
        if (return_value != NULL) {
 | 
			
		||||
            strncpy(temp_data, return_value, sizeof(temp_data));
 | 
			
		||||
            FDB_INFO("get the 'temp' value is: %s\n", temp_data);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    { /* CHANGE the KV value */
 | 
			
		||||
        char temp_data[10] = "38C";
 | 
			
		||||
 | 
			
		||||
        /* change the "temp" KV's value to "38.1" */
 | 
			
		||||
        fdb_kv_set(kvdb, "temp", temp_data);
 | 
			
		||||
        FDB_INFO("set 'temp' value to %s\n", temp_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    { /* DELETE the KV by name */
 | 
			
		||||
        fdb_kv_del(kvdb, "temp");
 | 
			
		||||
        FDB_INFO("delete the 'temp' finish\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FDB_INFO("===========================================================\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* FDB_USING_KVDB */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,120 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * @brief TSDB samples.
 | 
			
		||||
 *
 | 
			
		||||
 * Time series log (like TSDB) feature samples source file.
 | 
			
		||||
 *
 | 
			
		||||
 * TSL is time series log, the TSDB saved many TSLs.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <flashdb.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#ifdef FDB_USING_TSDB
 | 
			
		||||
 | 
			
		||||
#define FDB_LOG_TAG "[sample][tsdb]"
 | 
			
		||||
 | 
			
		||||
struct env_status {
 | 
			
		||||
    int temp;
 | 
			
		||||
    int humi;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool query_cb(fdb_tsl_t tsl, void *arg);
 | 
			
		||||
static bool query_by_time_cb(fdb_tsl_t tsl, void *arg);
 | 
			
		||||
static bool set_status_cb(fdb_tsl_t tsl, void *arg);
 | 
			
		||||
 | 
			
		||||
void tsdb_sample(fdb_tsdb_t tsdb)
 | 
			
		||||
{
 | 
			
		||||
    struct fdb_blob blob;
 | 
			
		||||
 | 
			
		||||
    FDB_INFO("==================== tsdb_sample ====================\n");
 | 
			
		||||
 | 
			
		||||
    { /* APPEND new TSL (time series log) */
 | 
			
		||||
        struct env_status status;
 | 
			
		||||
 | 
			
		||||
        /* append new log to TSDB */
 | 
			
		||||
        status.temp = 36;
 | 
			
		||||
        status.humi = 85;
 | 
			
		||||
        fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));
 | 
			
		||||
        FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi);
 | 
			
		||||
 | 
			
		||||
        status.temp = 38;
 | 
			
		||||
        status.humi = 90;
 | 
			
		||||
        fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));
 | 
			
		||||
        FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    { /* QUERY the TSDB */
 | 
			
		||||
        /* query all TSL in TSDB by iterator */
 | 
			
		||||
        fdb_tsl_iter(tsdb, query_cb, tsdb);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    { /* QUERY the TSDB by time */
 | 
			
		||||
        /* prepare query time (from 1970-01-01 00:00:00 to 2020-05-05 00:00:00) */
 | 
			
		||||
        struct tm tm_from = { .tm_year = 1970 - 1900, .tm_mon = 0, .tm_mday = 1, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 };
 | 
			
		||||
        struct tm tm_to = { .tm_year = 2020 - 1900, .tm_mon = 4, .tm_mday = 5, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 };
 | 
			
		||||
        time_t from_time = mktime(&tm_from), to_time = mktime(&tm_to);
 | 
			
		||||
        size_t count;
 | 
			
		||||
        /* query all TSL in TSDB by time */
 | 
			
		||||
        fdb_tsl_iter_by_time(tsdb, from_time, to_time, query_by_time_cb, tsdb);
 | 
			
		||||
        /* query all FDB_TSL_WRITE status TSL's count in TSDB by time */
 | 
			
		||||
        count = fdb_tsl_query_count(tsdb, from_time, to_time, FDB_TSL_WRITE);
 | 
			
		||||
        FDB_INFO("query count is: %zu\n", count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    { /* SET the TSL status */
 | 
			
		||||
        /* Change the TSL status by iterator or time iterator
 | 
			
		||||
         * set_status_cb: the change operation will in this callback
 | 
			
		||||
         *
 | 
			
		||||
         * NOTE: The actions to modify the state must be in order.
 | 
			
		||||
         *       like: FDB_TSL_WRITE -> FDB_TSL_USER_STATUS1 -> FDB_TSL_DELETED -> FDB_TSL_USER_STATUS2
 | 
			
		||||
         *       The intermediate states can also be ignored.
 | 
			
		||||
         *       such as: FDB_TSL_WRITE -> FDB_TSL_DELETED
 | 
			
		||||
         */
 | 
			
		||||
        fdb_tsl_iter(tsdb, set_status_cb, tsdb);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FDB_INFO("===========================================================\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool query_cb(fdb_tsl_t tsl, void *arg)
 | 
			
		||||
{
 | 
			
		||||
    struct fdb_blob blob;
 | 
			
		||||
    struct env_status status;
 | 
			
		||||
    fdb_tsdb_t db = arg;
 | 
			
		||||
 | 
			
		||||
    fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status))));
 | 
			
		||||
    FDB_INFO("[query_cb] queried a TSL: time: %ld, temp: %d, humi: %d\n", tsl->time, status.temp, status.humi);
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool query_by_time_cb(fdb_tsl_t tsl, void *arg)
 | 
			
		||||
{
 | 
			
		||||
    struct fdb_blob blob;
 | 
			
		||||
    struct env_status status;
 | 
			
		||||
    fdb_tsdb_t db = arg;
 | 
			
		||||
 | 
			
		||||
    fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status))));
 | 
			
		||||
    FDB_INFO("[query_by_time_cb] queried a TSL: time: %ld, temp: %d, humi: %d\n", tsl->time, status.temp, status.humi);
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool set_status_cb(fdb_tsl_t tsl, void *arg)
 | 
			
		||||
{
 | 
			
		||||
    fdb_tsdb_t db = arg;
 | 
			
		||||
 | 
			
		||||
    FDB_INFO("set the TSL (time %ld) status from %d to %d\n", tsl->time, tsl->status, FDB_TSL_USER_STATUS1);
 | 
			
		||||
    fdb_tsl_set_status(db, tsl, FDB_TSL_USER_STATUS1);
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* FDB_USING_TSDB */
 | 
			
		||||
| 
						 | 
				
			
			@ -36,6 +36,8 @@ extern int As830Ch4Init(void);
 | 
			
		|||
extern int Tb600bIaq10IaqInit(void);
 | 
			
		||||
extern int Tb600bTvoc10TvocInit(void);
 | 
			
		||||
extern int Tb600bWqHcho1osInit(void);
 | 
			
		||||
extern int QsFxWindDirectionInit(void);
 | 
			
		||||
extern int QsFsWindSpeedInit(void);
 | 
			
		||||
 | 
			
		||||
extern int lv_port_init(void);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -104,6 +106,14 @@ static struct InitDesc sensor_desc[] =
 | 
			
		|||
	{ "zg09_co2", Zg09Co2Init },
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SENSOR_QS_FX
 | 
			
		||||
	{ "qs_fx_wind_direction", QsFxWindDirectionInit },
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SENSOR_QS_FS
 | 
			
		||||
	{ "qs_fs_wind_speed", QsFsWindSpeedInit },
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SENSOR_AS830
 | 
			
		||||
	{ "ch4_as830", As830Ch4Init },
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,11 @@ menuconfig USING_CMSIS_5_DEMOAPP
 | 
			
		|||
            select IMAGE_PROCESSING_USING_TJPGD
 | 
			
		||||
            default n
 | 
			
		||||
 | 
			
		||||
        config USING_CMSIS_5_NN_DEMOAPP_VEG_CLASSIFY
 | 
			
		||||
            bool "Using CMSIS-5 NN demo app vegetable classify"
 | 
			
		||||
            select USING_IMAGE_PROCESSING
 | 
			
		||||
            select IMAGE_PROCESSING_USING_TJPGD
 | 
			
		||||
            default n
 | 
			
		||||
    endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
# CMSIS-NN vegetable classify example
 | 
			
		||||
 | 
			
		||||
This example uses CMSIS-NN to classify vegetable in real time under certain circumstances .
 | 
			
		||||
 | 
			
		||||
## Requirements:
 | 
			
		||||
- CMSIS-NN in Framework/knowing/cmsis_5
 | 
			
		||||
- **ov2640 need to be configured** in menuconfig "More Drivers->ov2640 driver" as follows
 | 
			
		||||
  - Output format (RGB565 mode)
 | 
			
		||||
  - (256) X direction resolution of outputimage
 | 
			
		||||
  - (256) Y direction resolution of outputimage
 | 
			
		||||
  - (512) X direction WINDOWS SIZE
 | 
			
		||||
  - (512) Y direction WINDOWS SIZE
 | 
			
		||||
 | 
			
		||||
## To run this demo:
 | 
			
		||||
- Set up and configure the corresponding hardware environment.
 | 
			
		||||
 | 
			
		||||
- Run demo by type the command
 | 
			
		||||
  ``` 
 | 
			
		||||
  cmsisnn_vegetable_classify
 | 
			
		||||
 | 
			
		||||
## Results
 | 
			
		||||
 | 
			
		||||
- **tomato**
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
- **potato**
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
- **pepper**
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
- **mushroom**
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
from building import *
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
cwd = GetCurrentDir()
 | 
			
		||||
 | 
			
		||||
src = Split('''
 | 
			
		||||
model/nn_vegetable_classify.c
 | 
			
		||||
cmsisnn_vegetable_classify.c
 | 
			
		||||
''')
 | 
			
		||||
 | 
			
		||||
path = [
 | 
			
		||||
    cwd + '/model',
 | 
			
		||||
    cwd + '/demo'
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
group = DefineGroup('CMSISNN vegetable classify application', src, depend = ['USING_CMSIS_5_NN_DEMOAPP_VEG_CLASSIFY'], CPPPATH = path)
 | 
			
		||||
 | 
			
		||||
Return('group')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,188 @@
 | 
			
		|||
#include <rtthread.h>
 | 
			
		||||
#include <rtdevice.h>
 | 
			
		||||
#include "stdio.h"
 | 
			
		||||
#include "string.h"
 | 
			
		||||
 | 
			
		||||
#ifdef OV2640_RGB565_MODE
 | 
			
		||||
#ifdef RT_USING_POSIX
 | 
			
		||||
#include <dfs_posix.h>
 | 
			
		||||
#include <dfs_poll.h>
 | 
			
		||||
#ifdef RT_USING_POSIX_TERMIOS
 | 
			
		||||
#include <posix_termios.h>
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <drv_ov2640.h>
 | 
			
		||||
#include <drv_lcd.h>
 | 
			
		||||
#include "nn_vegetable_classify.h"
 | 
			
		||||
#define JPEG_BUF_SIZE (2 * OV2640_X_RESOLUTION_IMAGE_OUTSIZE * OV2640_Y_RESOLUTION_IMAGE_OUTSIZE)
 | 
			
		||||
#define IOCTL_ERROR 1
 | 
			
		||||
 | 
			
		||||
static int fd = 0;
 | 
			
		||||
static int infer_times = 0;
 | 
			
		||||
static int photo_times = 0;
 | 
			
		||||
static int height = OV2640_X_RESOLUTION_IMAGE_OUTSIZE;
 | 
			
		||||
static int width = OV2640_Y_RESOLUTION_IMAGE_OUTSIZE;
 | 
			
		||||
static _ioctl_shoot_para shoot_para_t = {0};
 | 
			
		||||
const char *vegetable_label[] = {"mushroom", "pepper", "potato", "tomato"};
 | 
			
		||||
 | 
			
		||||
uint8_t *resized_buffer = NULL;
 | 
			
		||||
uint8_t *in_buffer = NULL;
 | 
			
		||||
 | 
			
		||||
int get_top_prediction_detection(q7_t *predictions)
 | 
			
		||||
{
 | 
			
		||||
  int max_ind = 0;
 | 
			
		||||
  int max_val = -128;
 | 
			
		||||
  for (int i = 0; i < 10; i++)
 | 
			
		||||
  {
 | 
			
		||||
    if (max_val < predictions[i])
 | 
			
		||||
    {
 | 
			
		||||
      max_val = predictions[i];
 | 
			
		||||
      max_ind = i;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return max_ind;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cmsisnn_inference_vegetable_classify(uint8_t *input_data)
 | 
			
		||||
{
 | 
			
		||||
  int8_t output_data[4];
 | 
			
		||||
  char output[50] = {0};
 | 
			
		||||
  char outputPrediction[50] = {0};
 | 
			
		||||
  memset(output, 0, 50);
 | 
			
		||||
  memset(outputPrediction, 0, 50);
 | 
			
		||||
 | 
			
		||||
  run_nn_sn_classify((int8_t *)input_data, output_data);
 | 
			
		||||
  arm_softmax_q7(output_data, 4, output_data);
 | 
			
		||||
 | 
			
		||||
  infer_times++;
 | 
			
		||||
  int top_ind = get_top_prediction_detection(output_data);
 | 
			
		||||
  printf("times:%d  Prediction:%s \r\n", infer_times, vegetable_label[top_ind]);
 | 
			
		||||
  sprintf(outputPrediction, "times:%d Prediction:%s        \r\n", infer_times, vegetable_label[top_ind]);
 | 
			
		||||
  lcd_show_string(1, 280, 240, 16, 16, outputPrediction, RED);
 | 
			
		||||
  return top_ind;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void resize_rgb888in_rgb565out(uint8_t *camera_image, uint16_t *resize_image)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t *psrc_temp = (uint8_t *)camera_image;
 | 
			
		||||
  uint16_t *pdst_temp = (uint16_t *)resize_image;
 | 
			
		||||
  for (int y = 0; y < height; y++)
 | 
			
		||||
  {
 | 
			
		||||
    for (int x = 0; x < width; x++)
 | 
			
		||||
    {
 | 
			
		||||
      *pdst_temp++ = (*psrc_temp++ & 0xF8) << 8 | (*psrc_temp++ & 0xFC) << 3 | *psrc_temp++ >> 3;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void resize_rgb565in_rgb888out(uint8_t *camera_image, uint8_t *resize_image)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t *psrc_temp = (uint8_t *)camera_image;
 | 
			
		||||
  uint8_t *pdst_temp = (uint8_t *)resize_image;
 | 
			
		||||
  for (int y = 0; y < height; y++)
 | 
			
		||||
  {
 | 
			
		||||
    for (int x = 0; x < width; x++)
 | 
			
		||||
    {
 | 
			
		||||
      uint8_t pixel_lo = *psrc_temp++;
 | 
			
		||||
      uint8_t pixel_hi = *psrc_temp++;
 | 
			
		||||
      *pdst_temp++ = (0xF8 & pixel_hi);
 | 
			
		||||
      *pdst_temp++ = ((0x07 & pixel_hi) << 5) | ((0xE0 & pixel_lo) >> 3);
 | 
			
		||||
      *pdst_temp++ = (0x1F & pixel_lo) << 3;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lcd_show_ov2640_thread_detection(uint8_t *rgbbuffer)
 | 
			
		||||
{
 | 
			
		||||
  int32_t ret = 0;
 | 
			
		||||
  while (1)
 | 
			
		||||
  {
 | 
			
		||||
    ret = ioctl(fd, IOCTRL_CAMERA_START_SHOT, &shoot_para_t);
 | 
			
		||||
    if (ret == IOCTL_ERROR)
 | 
			
		||||
    {
 | 
			
		||||
      printf("ov2640 can't wait event flag");
 | 
			
		||||
      free(rgbbuffer);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    lcd_fill_array(0, 0, OV2640_X_RESOLUTION_IMAGE_OUTSIZE, OV2640_Y_RESOLUTION_IMAGE_OUTSIZE, rgbbuffer);
 | 
			
		||||
 | 
			
		||||
    if (photo_times % 20 == 0)
 | 
			
		||||
    {
 | 
			
		||||
      resize_rgb565in_rgb888out(rgbbuffer, resized_buffer);
 | 
			
		||||
      int pixel = 0;
 | 
			
		||||
      for (int i = 0; i < 3 * width; i += 3 * width / CONV1_IN_DIM)
 | 
			
		||||
      {
 | 
			
		||||
        for (int j = 0; j < 3 * height; j += 3 * height / CONV1_IN_DIM)
 | 
			
		||||
        {
 | 
			
		||||
          for (int k = 0; k < 3; k++, pixel++)
 | 
			
		||||
          {
 | 
			
		||||
            *(in_buffer + pixel) = *(resized_buffer + 256 * i + j + k);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      cmsisnn_inference_vegetable_classify(in_buffer);
 | 
			
		||||
    }
 | 
			
		||||
    photo_times++;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmsisnn_vegetable_classify()
 | 
			
		||||
{
 | 
			
		||||
  fd = open("/dev/ov2640", O_RDONLY);
 | 
			
		||||
  if (fd < 0)
 | 
			
		||||
  {
 | 
			
		||||
    printf("open ov2640 fail !!");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  printf("memory_init \n\r");
 | 
			
		||||
  uint8_t *JpegBuffer = malloc(JPEG_BUF_SIZE);
 | 
			
		||||
  if (JpegBuffer == NULL)
 | 
			
		||||
  {
 | 
			
		||||
    printf("JpegBuffer senddata buf malloc error!\n");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  resized_buffer = malloc(3 * width * height);
 | 
			
		||||
  if (resized_buffer == NULL)
 | 
			
		||||
  {
 | 
			
		||||
    printf("Resized_buffer buf malloc error!\n");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  in_buffer = malloc(CONV1_IN_CH * CONV1_IN_DIM * CONV1_IN_DIM);
 | 
			
		||||
  if (in_buffer == NULL)
 | 
			
		||||
  {
 | 
			
		||||
    printf("In_buffer buf malloc error!\n");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  memory_init();
 | 
			
		||||
  printf("memory_init success\n\r");
 | 
			
		||||
  
 | 
			
		||||
  shoot_para_t.pdata = (uint32_t)JpegBuffer;
 | 
			
		||||
  shoot_para_t.length = JPEG_BUF_SIZE / 2;
 | 
			
		||||
 | 
			
		||||
  int result = 0;
 | 
			
		||||
  pthread_t tid = 0;
 | 
			
		||||
  pthread_attr_t attr;
 | 
			
		||||
  struct sched_param prio;
 | 
			
		||||
  prio.sched_priority = 8;
 | 
			
		||||
  size_t stack_size = 1024 * 11;
 | 
			
		||||
  pthread_attr_init(&attr);
 | 
			
		||||
  pthread_attr_setschedparam(&attr, &prio); 
 | 
			
		||||
  pthread_attr_setstacksize(&attr, stack_size);
 | 
			
		||||
 | 
			
		||||
  result = pthread_create(&tid, &attr, lcd_show_ov2640_thread_detection, JpegBuffer);
 | 
			
		||||
  if (0 == result) {
 | 
			
		||||
      printf("thread_detect_entry successfully!\n");
 | 
			
		||||
  } else {
 | 
			
		||||
      printf("thread_detect_entry failed! error code is %d.\n", result);
 | 
			
		||||
      close(fd);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __RT_THREAD_H__
 | 
			
		||||
MSH_CMD_EXPORT(cmsisnn_vegetable_classify, classify vegetable using cmsis-nn);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 144 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 140 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 126 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 141 KiB  | 
| 
						 | 
				
			
			@ -0,0 +1,108 @@
 | 
			
		|||
#include "nn_vegetable_classify.h"
 | 
			
		||||
 | 
			
		||||
static const q7_t conv1_w[CONV1_WT_SHAPE] = CONV1_WT;
 | 
			
		||||
static const q7_t conv1_b[CONV1_BIAS_SHAPE] = CONV1_BIAS;
 | 
			
		||||
static const q7_t conv2_w[CONV2_WT_SHAPE] = CONV2_WT;
 | 
			
		||||
static const q7_t conv2_b[CONV2_BIAS_SHAPE] = CONV2_BIAS;
 | 
			
		||||
// static const q7_t conv3_w[CONV3_WT_SHAPE] =  CONV3_WT;
 | 
			
		||||
// static const q7_t conv3_b[CONV3_BIAS_SHAPE] = CONV3_BIAS;
 | 
			
		||||
static const q7_t interface_w[INTERFACE_WT_SHAPE] = INTERFACE_WT;
 | 
			
		||||
static const q7_t interface_b[INTERFACE_BIAS_SHAPE] = INTERFACE_BIAS;
 | 
			
		||||
static const q7_t linear_w[LINEAR_WT_SHAPE] = LINEAR_WT;
 | 
			
		||||
static const q7_t linear_b[LINEAR_BIAS_SHAPE] = LINEAR_BIAS;
 | 
			
		||||
 | 
			
		||||
q7_t *conv1_out = NULL;
 | 
			
		||||
q7_t *pool1_out = NULL;
 | 
			
		||||
q7_t *conv2_out = NULL;
 | 
			
		||||
q7_t *pool2_out = NULL;
 | 
			
		||||
//  q7_t *conv3_out = NULL ;
 | 
			
		||||
q7_t *interface_out = NULL;
 | 
			
		||||
q7_t *linear_out = NULL;
 | 
			
		||||
q7_t *y_out = NULL;
 | 
			
		||||
q7_t *conv_buffer = NULL;
 | 
			
		||||
q7_t *fc_buffer = NULL;
 | 
			
		||||
 | 
			
		||||
void memory_init()
 | 
			
		||||
{
 | 
			
		||||
  static int flag = 0;
 | 
			
		||||
  if (flag == 0)
 | 
			
		||||
  {
 | 
			
		||||
    conv1_out = malloc(CONV1_OUT_CH * CONV1_OUT_DIM * CONV1_OUT_DIM);
 | 
			
		||||
    if (conv1_out == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      printf("conv1_out malloc failed...\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    pool1_out = malloc(CONV1_OUT_CH * POOL1_OUT_DIM * POOL1_OUT_DIM);
 | 
			
		||||
    if (pool1_out == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      printf("pool1_out malloc failed...\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    conv2_out = malloc(CONV2_OUT_CH * CONV2_OUT_DIM * CONV2_OUT_DIM);
 | 
			
		||||
    if (conv2_out == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      printf("conv2_out malloc failed...\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    pool2_out = malloc(CONV2_OUT_CH * POOL2_OUT_DIM * POOL2_OUT_DIM);
 | 
			
		||||
    if (pool2_out == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      printf("pool2_out malloc failed...\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    interface_out = malloc(INTERFACE_OUT_DIM);
 | 
			
		||||
    if (interface_out == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      printf("interface_out malloc failed...\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    linear_out = malloc(LINEAR_OUT_DIM);
 | 
			
		||||
    if (linear_out == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      printf("linear_out malloc failed...\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    y_out = malloc(LINEAR_OUT_DIM);
 | 
			
		||||
    if (y_out == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      printf("y_out malloc failed...\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    conv_buffer = malloc(MAX_CONV_BUFFER_SIZE);
 | 
			
		||||
    if (conv_buffer == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      printf("conv_buffer malloc failed...\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    fc_buffer = malloc(MAX_FC_BUFFER);
 | 
			
		||||
    if (fc_buffer == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      printf("fc_buffer malloc failed...\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void run_nn_sn_classify(q7_t *input_data, q7_t *output_data)
 | 
			
		||||
{
 | 
			
		||||
  for (int i = 0; i < CONV1_IN_CH * CONV1_IN_DIM * CONV1_IN_DIM; i++)
 | 
			
		||||
  {
 | 
			
		||||
    input_data[i] = input_data[i] - 127;
 | 
			
		||||
  }
 | 
			
		||||
  arm_convolve_HWC_q7_basic(input_data, CONV1_IN_DIM, CONV1_IN_CH, conv1_w, CONV1_OUT_CH, CONV1_KER_DIM, CONV1_PAD, CONV1_STRIDE, conv1_b, CONV1_BIAS_LSHIFT, CONV1_OUT_RSHIFT, conv1_out, CONV1_OUT_DIM, (q15_t *)conv_buffer, fc_buffer);
 | 
			
		||||
  arm_maxpool_q7_HWC(conv1_out, POOL1_IN_DIM, POOL1_IN_CH, POOL1_KER_DIM, POOL1_PAD, POOL1_STRIDE, POOL1_OUT_DIM, NULL, pool1_out);
 | 
			
		||||
  arm_relu_q7(pool1_out, POOL1_OUT_DIM * POOL1_OUT_DIM * CONV1_OUT_CH);
 | 
			
		||||
  arm_convolve_HWC_q7_basic(pool1_out, CONV2_IN_DIM, CONV2_IN_CH, conv2_w, CONV2_OUT_CH, CONV2_KER_DIM, CONV2_PAD, CONV2_STRIDE, conv2_b, CONV2_BIAS_LSHIFT, CONV2_OUT_RSHIFT, conv2_out, CONV2_OUT_DIM, (q15_t *)conv_buffer, NULL);
 | 
			
		||||
  arm_maxpool_q7_HWC(conv2_out, POOL2_IN_DIM, POOL2_IN_CH, POOL2_KER_DIM, POOL2_PAD, POOL2_STRIDE, POOL2_OUT_DIM, NULL, pool2_out);
 | 
			
		||||
  arm_relu_q7(pool2_out, POOL2_OUT_DIM * POOL2_OUT_DIM * CONV2_OUT_CH);
 | 
			
		||||
  // printf("1\n");
 | 
			
		||||
  // arm_convolve_HWC_q7_basic(pool2_out, CONV3_IN_DIM, CONV3_IN_CH, conv3_w, CONV3_OUT_CH, CONV3_KER_DIM,
 | 
			
		||||
	// 					  CONV3_PAD, CONV3_STRIDE, conv3_b, CONV3_BIAS_LSHIFT, CONV3_OUT_RSHIFT, conv3_out,
 | 
			
		||||
	// 					  CONV3_OUT_DIM, (q15_t *) conv_buffer, NULL);
 | 
			
		||||
  // arm_relu_q7(conv3_out, CONV3_OUT_DIM * CONV3_OUT_DIM * CONV3_OUT_CH);
 | 
			
		||||
  // printf("2\n");
 | 
			
		||||
  arm_fully_connected_q7_opt(pool2_out, interface_w, INTERFACE_IN_DIM, INTERFACE_OUT_DIM, INTERFACE_BIAS_LSHIFT, INTERFACE_OUT_RSHIFT, interface_b, interface_out, (q15_t *)fc_buffer);
 | 
			
		||||
  arm_relu_q7(interface_out, INTERFACE_OUT_DIM);
 | 
			
		||||
  arm_fully_connected_q7_opt(interface_out, linear_w, LINEAR_IN_DIM, LINEAR_OUT_DIM, LINEAR_BIAS_LSHIFT, LINEAR_OUT_RSHIFT, linear_b, output_data, (q15_t *)fc_buffer);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
#ifndef __NN_H__
 | 
			
		||||
#define __NN_H__
 | 
			
		||||
 | 
			
		||||
#include <transform.h>
 | 
			
		||||
#include "arm_math.h"
 | 
			
		||||
#include "arm_nnfunctions.h"
 | 
			
		||||
#include "parameter_vegetable_classify.h"
 | 
			
		||||
#include "weights_vegetable_classify.h"
 | 
			
		||||
 | 
			
		||||
void run_nn_detection(q7_t* input_data, q7_t* output_data);
 | 
			
		||||
void memory_init();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
#define CONV1_IN_CH 3
 | 
			
		||||
#define CONV1_OUT_CH 32
 | 
			
		||||
#define CONV1_KER_DIM 3
 | 
			
		||||
#define CONV1_PAD 0
 | 
			
		||||
#define CONV1_STRIDE 1
 | 
			
		||||
#define CONV1_IN_DIM 32
 | 
			
		||||
#define CONV1_OUT_DIM 30
 | 
			
		||||
#define MAX_CONV_BUFFER_SIZE 3096
 | 
			
		||||
#define POOL1_IN_CH 32
 | 
			
		||||
#define POOL1_KER_DIM 2
 | 
			
		||||
#define POOL1_PAD 0
 | 
			
		||||
#define POOL1_STRIDE 2
 | 
			
		||||
#define POOL1_IN_DIM 30
 | 
			
		||||
#define POOL1_OUT_DIM 15
 | 
			
		||||
#define CONV2_IN_CH 32
 | 
			
		||||
#define CONV2_OUT_CH 32
 | 
			
		||||
#define CONV2_KER_DIM 3
 | 
			
		||||
#define CONV2_PAD 0
 | 
			
		||||
#define CONV2_STRIDE 1
 | 
			
		||||
#define CONV2_IN_DIM 15
 | 
			
		||||
#define CONV2_OUT_DIM 13
 | 
			
		||||
#define POOL2_IN_CH 32
 | 
			
		||||
#define POOL2_KER_DIM 2
 | 
			
		||||
#define POOL2_PAD 0
 | 
			
		||||
#define POOL2_STRIDE 2
 | 
			
		||||
#define POOL2_IN_DIM 13
 | 
			
		||||
#define POOL2_OUT_DIM 6
 | 
			
		||||
#define INTERFACE_OUT_DIM 32
 | 
			
		||||
#define INTERFACE_IN_DIM 1152
 | 
			
		||||
#define MAX_FC_BUFFER 3096
 | 
			
		||||
#define LINEAR_OUT_DIM 4
 | 
			
		||||
#define LINEAR_IN_DIM 32
 | 
			
		||||
#define CONV1_BIAS_LSHIFT 6
 | 
			
		||||
#define CONV1_OUT_RSHIFT 9
 | 
			
		||||
#define CONV1_WEIGHT_Q 8
 | 
			
		||||
#define CONV1_BIAS_Q 8
 | 
			
		||||
#define CONV1_INPUT_Q 6
 | 
			
		||||
#define CONV1_OUT_Q 5
 | 
			
		||||
#define CONV2_BIAS_LSHIFT 4
 | 
			
		||||
#define CONV2_OUT_RSHIFT 10
 | 
			
		||||
#define CONV2_WEIGHT_Q 9
 | 
			
		||||
#define CONV2_BIAS_Q 10
 | 
			
		||||
#define CONV2_INPUT_Q 5
 | 
			
		||||
#define CONV2_OUT_Q 4
 | 
			
		||||
#define INTERFACE_BIAS_LSHIFT 3
 | 
			
		||||
#define INTERFACE_OUT_RSHIFT 11
 | 
			
		||||
#define INTERFACE_WEIGHT_Q 9
 | 
			
		||||
#define INTERFACE_BIAS_Q 10
 | 
			
		||||
#define INTERFACE_INPUT_Q 4
 | 
			
		||||
#define INTERFACE_OUT_Q 2
 | 
			
		||||
#define LINEAR_BIAS_LSHIFT 0
 | 
			
		||||
#define LINEAR_OUT_RSHIFT 7
 | 
			
		||||
#define LINEAR_WEIGHT_Q 7
 | 
			
		||||
#define LINEAR_BIAS_Q 9
 | 
			
		||||
#define LINEAR_INPUT_Q 2
 | 
			
		||||
#define LINEAR_OUT_Q 2
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
config IMAGE_PROCESSING_TJPGDEC_APP
 | 
			
		||||
    bool "image processing apps/TJpgDec(example)"
 | 
			
		||||
    select USING_IMAGE_PROCESSING
 | 
			
		||||
    select IMAGE_PROCESSING_USING_TJPGD
 | 
			
		||||
    default n
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,6 +53,10 @@ menu "sensor app"
 | 
			
		|||
                    config APPLICATION_SENSOR_CO2_ZG09
 | 
			
		||||
                    bool "Using sensor ZG09 apps"
 | 
			
		||||
                    default n
 | 
			
		||||
 | 
			
		||||
                    config APPLICATION_SENSOR_CO2_G8S
 | 
			
		||||
                    bool "Using sensor G8S apps"
 | 
			
		||||
                    default n
 | 
			
		||||
                endif
 | 
			
		||||
 | 
			
		||||
            menuconfig APPLICATION_SENSOR_PM1_0
 | 
			
		||||
| 
						 | 
				
			
			@ -122,7 +126,36 @@ menu "sensor app"
 | 
			
		|||
                    endif
 | 
			
		||||
 | 
			
		||||
                endif
 | 
			
		||||
                
 | 
			
		||||
            menuconfig APPLICATION_SENSOR_WINDDIRECTION
 | 
			
		||||
                bool "Using sensor wind direction apps"
 | 
			
		||||
                default n
 | 
			
		||||
 | 
			
		||||
                if APPLICATION_SENSOR_WINDDIRECTION
 | 
			
		||||
                    config APPLICATION_SENSOR_WINDDIRECTION_QS_FX
 | 
			
		||||
                    bool "Using sensor QS-FX apps"
 | 
			
		||||
                    default n
 | 
			
		||||
                endif
 | 
			
		||||
 | 
			
		||||
            menuconfig APPLICATION_SENSOR_WINDSPEED
 | 
			
		||||
                bool "Using sensor wind speed apps"
 | 
			
		||||
                default n
 | 
			
		||||
 | 
			
		||||
                if APPLICATION_SENSOR_WINDSPEED
 | 
			
		||||
                    config APPLICATION_SENSOR_WINDSPEED_QS_FS
 | 
			
		||||
                    bool "Using sensor QS-FS apps"
 | 
			
		||||
                    default n
 | 
			
		||||
                endif
 | 
			
		||||
 | 
			
		||||
            menuconfig APPLICATION_SENSOR_ALTITUDE
 | 
			
		||||
                bool "Using sensor altitude apps"
 | 
			
		||||
                default n
 | 
			
		||||
 | 
			
		||||
                if APPLICATION_SENSOR_ALTITUDE
 | 
			
		||||
                    config APPLICATION_SENSOR_ALTITUDE_BMP180
 | 
			
		||||
                    bool "Using sensor BMP180 apps"
 | 
			
		||||
                    default n
 | 
			
		||||
                endif
 | 
			
		||||
        endif
 | 
			
		||||
 | 
			
		||||
endmenu
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,6 +74,10 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
 | 
			
		|||
        SRC_FILES += co2_zg09.c
 | 
			
		||||
    endif
 | 
			
		||||
 | 
			
		||||
    ifeq ($(CONFIG_APPLICATION_SENSOR_CO2_G8S), y)
 | 
			
		||||
        SRC_FILES += co2_g8s.c
 | 
			
		||||
    endif
 | 
			
		||||
 | 
			
		||||
    ifeq ($(CONFIG_APPLICATION_SENSOR_PM1_0_PS5308), y)
 | 
			
		||||
        SRC_FILES += pm1_0_ps5308.c
 | 
			
		||||
    endif
 | 
			
		||||
| 
						 | 
				
			
			@ -98,6 +102,18 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
 | 
			
		|||
        SRC_FILES += temperature_hs300x.c
 | 
			
		||||
    endif
 | 
			
		||||
 | 
			
		||||
    ifeq ($(CONFIG_APPLICATION_SENSOR_WINDDIRECTION_QS_FX), y)
 | 
			
		||||
        SRC_FILES += winddirection_qs_fx.c
 | 
			
		||||
    endif
 | 
			
		||||
 | 
			
		||||
    ifeq ($(CONFIG_APPLICATION_SENSOR_WINDSPEED_QS_FS), y)
 | 
			
		||||
        SRC_FILES += windspeed_qs_fs.c
 | 
			
		||||
    endif
 | 
			
		||||
 | 
			
		||||
    ifeq ($(CONFIG_APPLICATION_SENSOR_ALTITUDE_BMP180), y)
 | 
			
		||||
        SRC_FILES += altitude_bmp180.c
 | 
			
		||||
    endif
 | 
			
		||||
 | 
			
		||||
    include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2020 AIIT XUOS Lab
 | 
			
		||||
* XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file altitude_bmp180.c
 | 
			
		||||
 * @brief BMP180 altitude example
 | 
			
		||||
 * @version 1.1
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.12.23
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <user_api.h>
 | 
			
		||||
#include <sensor.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Read a altitude
 | 
			
		||||
 * @return 0
 | 
			
		||||
 */
 | 
			
		||||
void AltitudeBmp180(void)
 | 
			
		||||
{
 | 
			
		||||
    int32 altitude;
 | 
			
		||||
    struct SensorQuantity *p_altitude = SensorQuantityFind(SENSOR_QUANTITY_BMP180_ALTITUDE, SENSOR_QUANTITY_ALTITUDE);
 | 
			
		||||
    SensorQuantityOpen(p_altitude);
 | 
			
		||||
    altitude = SensorQuantityRead(p_altitude);
 | 
			
		||||
 | 
			
		||||
    printf("Altitude Pressure : %d Pa\n", altitude);
 | 
			
		||||
 | 
			
		||||
    PrivTaskDelay(1000);
 | 
			
		||||
    SensorQuantityClose(p_altitude);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2020 AIIT XUOS Lab
 | 
			
		||||
* XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file co2_g8s.c
 | 
			
		||||
 * @brief G8S CO2 example
 | 
			
		||||
 * @version 1.1
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.12.23
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <user_api.h>
 | 
			
		||||
#include <sensor.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Read a CO2
 | 
			
		||||
 * @return 0
 | 
			
		||||
 */
 | 
			
		||||
void Co2G8s(void)
 | 
			
		||||
{
 | 
			
		||||
    struct SensorQuantity *co2 = SensorQuantityFind(SENSOR_QUANTITY_G8S_CO2, SENSOR_QUANTITY_CO2);
 | 
			
		||||
    SensorQuantityOpen(co2);
 | 
			
		||||
    printf("CO2 : %d ppm\n", SensorQuantityRead(co2));
 | 
			
		||||
    SensorQuantityClose(co2);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2020 AIIT XUOS Lab
 | 
			
		||||
* XiOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file winddirection_qs_fx.c
 | 
			
		||||
 * @brief qs-fx wind direction example
 | 
			
		||||
 * @version 1.1
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.12.14
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <transform.h>
 | 
			
		||||
#include <sensor.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Read a wind direction
 | 
			
		||||
 * @return 0
 | 
			
		||||
 */
 | 
			
		||||
void WindDirectionQsFx(void)
 | 
			
		||||
{
 | 
			
		||||
    struct SensorQuantity *wind_direction = SensorQuantityFind(SENSOR_QUANTITY_QS_FX_WINDDIRECTION, SENSOR_QUANTITY_WINDDIRECTION);
 | 
			
		||||
    SensorQuantityOpen(wind_direction);
 | 
			
		||||
    PrivTaskDelay(2000);
 | 
			
		||||
    uint16 result = SensorQuantityRead(wind_direction);
 | 
			
		||||
    printf("wind direction : %d degree\n", result);
 | 
			
		||||
    SensorQuantityClose(wind_direction);
 | 
			
		||||
}
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN, WindDirectionQsFx, WindDirectionQsFx, WindDirectionQsFx function);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2020 AIIT XUOS Lab
 | 
			
		||||
* XiOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file windspeed_qs_fs.c
 | 
			
		||||
 * @brief qs-fx wind direction example
 | 
			
		||||
 * @version 1.1
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.12.14
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <transform.h>
 | 
			
		||||
#include <sensor.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Read a wind speed
 | 
			
		||||
 * @return 0
 | 
			
		||||
 */
 | 
			
		||||
void WindSpeedQsFs(void)
 | 
			
		||||
{
 | 
			
		||||
    struct SensorQuantity *wind_speed = SensorQuantityFind(SENSOR_QUANTITY_QS_FS_WINDSPEED, SENSOR_QUANTITY_WINDSPEED);
 | 
			
		||||
    SensorQuantityOpen(wind_speed);
 | 
			
		||||
    PrivTaskDelay(2000);
 | 
			
		||||
    uint16 result = SensorQuantityRead(wind_speed);
 | 
			
		||||
    printf("wind speed : %d.%d m/s\n", result/10, result%10);
 | 
			
		||||
    SensorQuantityClose(wind_speed);
 | 
			
		||||
}
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN, WindSpeedQsFs, WindSpeedQsFs, WindSpeedQsFs function);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ int AdapterFrameworkInit(void)
 | 
			
		|||
    AppInitDoubleList(&adapter_list);
 | 
			
		||||
 | 
			
		||||
    ret = PrivMutexCreate(&adapter_list_lock, 0);
 | 
			
		||||
    if(ret < 0) {
 | 
			
		||||
    if(ret != 0) {
 | 
			
		||||
        printf("AdapterFrameworkInit mutex create failed.\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,11 +50,16 @@ AdapterType AdapterDeviceFindByName(const char *name)
 | 
			
		|||
{
 | 
			
		||||
    struct Adapter *ret = NULL;
 | 
			
		||||
    struct DoublelistNode *node;
 | 
			
		||||
    int status = 0;
 | 
			
		||||
 | 
			
		||||
    if (NULL == name)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    PrivMutexObtain(&adapter_list_lock);
 | 
			
		||||
    status = PrivMutexObtain(&adapter_list_lock);
 | 
			
		||||
    if (status != 0){
 | 
			
		||||
       printf("%s:pthread_mutex_lock failed, status=%d\n",__func__,status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DOUBLE_LIST_FOR_EACH(node, &adapter_list) {
 | 
			
		||||
        struct Adapter *adapter = CONTAINER_OF(node,
 | 
			
		||||
                struct Adapter, link);
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +69,11 @@ AdapterType AdapterDeviceFindByName(const char *name)
 | 
			
		|||
        }
 | 
			
		||||
        printf("PrivMutexObtain in loop\n");
 | 
			
		||||
    }
 | 
			
		||||
    PrivMutexAbandon(&adapter_list_lock);
 | 
			
		||||
 | 
			
		||||
    status = PrivMutexAbandon(&adapter_list_lock);
 | 
			
		||||
    if (status != 0){
 | 
			
		||||
       printf("%s:pthread_mutex_unlock failed, status=%d\n",__func__,status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +85,7 @@ AdapterType AdapterDeviceFindByName(const char *name)
 | 
			
		|||
 */
 | 
			
		||||
int AdapterDeviceRegister(struct Adapter *adapter)
 | 
			
		||||
{
 | 
			
		||||
    int status = 0;
 | 
			
		||||
    if (NULL == adapter )
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -84,9 +94,17 @@ int AdapterDeviceRegister(struct Adapter *adapter)
 | 
			
		|||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    PrivMutexObtain(&adapter_list_lock);
 | 
			
		||||
    status = PrivMutexObtain(&adapter_list_lock);
 | 
			
		||||
    if (status != 0){
 | 
			
		||||
       printf("%s:pthread_mutex_lock failed, status=%d\n",__func__,status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    AppDoubleListInsertNodeAfter(&adapter_list, &adapter->link);
 | 
			
		||||
    PrivMutexAbandon(&adapter_list_lock);
 | 
			
		||||
    
 | 
			
		||||
    status = PrivMutexAbandon(&adapter_list_lock);
 | 
			
		||||
    if (status != 0){
 | 
			
		||||
       printf("%s:pthread_mutex_unlock failed, status=%d\n",__func__,status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    adapter->adapter_status = REGISTERED;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -100,11 +118,20 @@ int AdapterDeviceRegister(struct Adapter *adapter)
 | 
			
		|||
 */
 | 
			
		||||
int AdapterDeviceUnregister(struct Adapter *adapter)
 | 
			
		||||
{
 | 
			
		||||
    int status = 0;
 | 
			
		||||
    if (!adapter)
 | 
			
		||||
        return -1;
 | 
			
		||||
    PrivMutexObtain(&adapter_list_lock);
 | 
			
		||||
    status = PrivMutexObtain(&adapter_list_lock);
 | 
			
		||||
    if (status != 0){
 | 
			
		||||
       printf("%s:pthread_mutex_lock failed, status=%d\n",__func__,status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    AppDoubleListRmNode(&adapter->link);
 | 
			
		||||
    PrivMutexAbandon(&adapter_list_lock);
 | 
			
		||||
 | 
			
		||||
    status = PrivMutexAbandon(&adapter_list_lock);
 | 
			
		||||
    if (status != 0){
 | 
			
		||||
       printf("%s:pthread_mutex_unlock failed, status=%d\n",__func__,status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    adapter->adapter_status = UNREGISTERED;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,8 @@ config ADAPTER_ETHERCAT_HFA21
 | 
			
		|||
        default "hfa21_ethercat"
 | 
			
		||||
 | 
			
		||||
config ADAPTER_ETHERCAT_HFA21_ROLE
 | 
			
		||||
        bool "support ethercat role configure"
 | 
			
		||||
        default y
 | 
			
		||||
        choice 
 | 
			
		||||
        prompt "EtherCAT adapter select net role type "
 | 
			
		||||
        default AS_ETHERCAT_SLAVE_ROLE
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
############################################################################
 | 
			
		||||
# APP_Framework/Framework/connection/lora/Make.defs
 | 
			
		||||
############################################################################
 | 
			
		||||
ifneq ($(CONFIG_ADAPTER_SX1278),)
 | 
			
		||||
CONFIGURED_APPS += $(APPDIR)/../../../APP_Framework/Framework/connection/lora
 | 
			
		||||
endif
 | 
			
		||||
include $(wildcard $(APPDIR)/../../../APP_Framework/Framework/connection/lora/*/Make.defs)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,16 @@
 | 
			
		|||
SRC_FILES := adapter_lora.c
 | 
			
		||||
include $(KERNEL_ROOT)/.config
 | 
			
		||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
 | 
			
		||||
    include $(APPDIR)/Make.defs
 | 
			
		||||
    CSRCS += adapter_lora.c
 | 
			
		||||
    include $(APPDIR)/Application.mk
 | 
			
		||||
 | 
			
		||||
ifeq ($(CONFIG_ADAPTER_SX1278),y)
 | 
			
		||||
	SRC_DIR += sx1278
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
 | 
			
		||||
    SRC_FILES := adapter_lora.c
 | 
			
		||||
    ifeq ($(CONFIG_ADAPTER_SX1278),y)
 | 
			
		||||
        SRC_DIR += sx1278
 | 
			
		||||
    endif
 | 
			
		||||
    include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ extern AdapterProductInfoType Sx1278Attach(struct Adapter *adapter);
 | 
			
		|||
#define ADAPTER_LORA_NAME "lora"
 | 
			
		||||
#define ADAPTER_LORA_CLIENT_NUM 6
 | 
			
		||||
#define ADAPTER_LORA_DATA_LENGTH 128
 | 
			
		||||
#define ADAPTER_LORA_RECV_DATA_LENGTH 256
 | 
			
		||||
 | 
			
		||||
#define ADAPTER_LORA_DATA_HEAD            0x3C
 | 
			
		||||
#define ADAPTER_LORA_NET_PANID            0x0102
 | 
			
		||||
| 
						 | 
				
			
			@ -96,12 +97,13 @@ struct LoraClientParam
 | 
			
		|||
struct LoraDataFormat
 | 
			
		||||
{
 | 
			
		||||
    uint8 flame_head;
 | 
			
		||||
    uint8 reserved[3];
 | 
			
		||||
    uint32 length;
 | 
			
		||||
    uint16 panid;
 | 
			
		||||
    uint8 client_id;
 | 
			
		||||
    uint8 gateway_id;
 | 
			
		||||
 | 
			
		||||
    uint8 data_type;
 | 
			
		||||
    uint16 data_type;
 | 
			
		||||
    uint8 data[ADAPTER_LORA_DATA_LENGTH];
 | 
			
		||||
 | 
			
		||||
    uint16 crc16;
 | 
			
		||||
| 
						 | 
				
			
			@ -150,6 +152,35 @@ static int LoraCrc16Check(uint8 *data, uint16 length)
 | 
			
		|||
        return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Lora receive data check
 | 
			
		||||
 * @param data receive data buffer
 | 
			
		||||
 * @param length receive data length
 | 
			
		||||
 * @param recv_data LoraDataFormat data
 | 
			
		||||
 */
 | 
			
		||||
static int LoraReceiveDataCheck(uint8 *data, uint16 length, struct LoraDataFormat *recv_data)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    uint32 recv_data_length = 0;
 | 
			
		||||
    for ( i = 0; i < length; i ++) {
 | 
			
		||||
        if (ADAPTER_LORA_DATA_HEAD == data[i]) {
 | 
			
		||||
#ifdef ADD_NUTTX_FETURES
 | 
			
		||||
            /*Big-Endian*/
 | 
			
		||||
            recv_data_length = (data[i + 4] & 0xFF) | ((data[i + 5] & 0xFF) << 8) | ((data[i + 6] & 0xFF) << 16) | ((data[i + 7] & 0xFF) << 24);
 | 
			
		||||
#else
 | 
			
		||||
            /*Little-Endian*/
 | 
			
		||||
            recv_data_length = ((data[i + 4] & 0xFF) << 24) | ((data[i + 5] & 0xFF) << 16) | ((data[i + 6] & 0xFF) << 8) | (data[i + 7] & 0xFF);
 | 
			
		||||
#endif
 | 
			
		||||
            if (sizeof(struct LoraDataFormat) == recv_data_length) {
 | 
			
		||||
                memcpy(recv_data, (uint8 *)(data + i), sizeof(struct LoraDataFormat));
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Lora Gateway reply connect request to Client
 | 
			
		||||
 * @param adapter Lora adapter pointer
 | 
			
		||||
| 
						 | 
				
			
			@ -338,6 +369,10 @@ static int LoraClientSendData(struct Adapter *adapter, void *send_buf, int lengt
 | 
			
		|||
static int LoraGateWayDataAnalyze(struct Adapter *adapter, struct LoraDataFormat *gateway_recv_data)
 | 
			
		||||
{
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
    printf("%s:gateway_recv_data\n",__func__);
 | 
			
		||||
    printf("head 0x%x length %d panid 0x%x data_type 0x%x client_id 0x%x gateway_id 0x%x crc 0x%x\n",
 | 
			
		||||
        gateway_recv_data->flame_head, gateway_recv_data->length, gateway_recv_data->panid, gateway_recv_data->data_type,
 | 
			
		||||
        gateway_recv_data->client_id, gateway_recv_data->gateway_id, gateway_recv_data->crc16);
 | 
			
		||||
 | 
			
		||||
    if (LoraCrc16Check((uint8 *)gateway_recv_data, sizeof(struct LoraDataFormat)) < 0) {
 | 
			
		||||
        printf("LoraGateWayDataAnalyze CRC check error\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -372,19 +407,22 @@ static int LoraGateWayDataAnalyze(struct Adapter *adapter, struct LoraDataFormat
 | 
			
		|||
static int LoraClientDataAnalyze(struct Adapter *adapter, void *send_buf, int length)
 | 
			
		||||
{
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
    uint8 lora_recv_data[ADAPTER_LORA_RECV_DATA_LENGTH] = {0};
 | 
			
		||||
    
 | 
			
		||||
    struct LoraDataFormat *client_recv_data = PrivMalloc(sizeof(struct LoraDataFormat));
 | 
			
		||||
 | 
			
		||||
    memset(client_recv_data, 0, sizeof(struct LoraDataFormat));
 | 
			
		||||
    
 | 
			
		||||
    ret = AdapterDeviceRecv(adapter, client_recv_data, sizeof(struct LoraDataFormat));
 | 
			
		||||
    if (0 == ret) {
 | 
			
		||||
    ret = AdapterDeviceRecv(adapter, lora_recv_data, ADAPTER_LORA_RECV_DATA_LENGTH);
 | 
			
		||||
    if (ret <= 0) {
 | 
			
		||||
        printf("LoraClientDataAnalyze recv error.Just return\n");
 | 
			
		||||
        PrivFree(client_recv_data);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    printf("client_recv_data\n");
 | 
			
		||||
    LoraReceiveDataCheck(lora_recv_data, ADAPTER_LORA_RECV_DATA_LENGTH, client_recv_data);
 | 
			
		||||
 | 
			
		||||
    printf("%s:client_recv_data\n",__func__);
 | 
			
		||||
    printf("head 0x%x length %d panid 0x%x data_type 0x%x client_id 0x%x gateway_id 0x%x crc 0x%x\n",
 | 
			
		||||
        client_recv_data->flame_head, client_recv_data->length, client_recv_data->panid, client_recv_data->data_type,
 | 
			
		||||
        client_recv_data->client_id, client_recv_data->gateway_id, client_recv_data->crc16);
 | 
			
		||||
| 
						 | 
				
			
			@ -437,6 +475,11 @@ static int LoraClientJoinNet(struct Adapter *adapter, unsigned short panid)
 | 
			
		|||
    client_join_data.data_type = ADAPTER_LORA_DATA_TYPE_JOIN;
 | 
			
		||||
    client_join_data.client_id = adapter->net_role_id;
 | 
			
		||||
    client_join_data.crc16 = LoraCrc16((uint8 *)&client_join_data, sizeof(struct LoraDataFormat) - 2);
 | 
			
		||||
 | 
			
		||||
    printf("%s:client_join_data\n",__func__);
 | 
			
		||||
    printf("head 0x%x length %d panid 0x%x data_type 0x%x client_id 0x%x gateway_id 0x%x crc 0x%x\n",
 | 
			
		||||
        client_join_data.flame_head, client_join_data.length, client_join_data.panid, client_join_data.data_type,
 | 
			
		||||
        client_join_data.client_id, client_join_data.gateway_id, client_join_data.crc16);
 | 
			
		||||
    
 | 
			
		||||
    if (AdapterDeviceJoin(adapter, (uint8 *)&client_join_data) < 0) {
 | 
			
		||||
        return -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -479,15 +522,20 @@ static int LoraClientQuitNet(struct Adapter *adapter, unsigned short panid)
 | 
			
		|||
int LoraGatewayProcess(struct Adapter *lora_adapter, struct LoraGatewayParam *gateway, struct LoraDataFormat *gateway_recv_data)
 | 
			
		||||
{
 | 
			
		||||
    int i, ret = 0;
 | 
			
		||||
    uint8 lora_recv_data[ADAPTER_LORA_RECV_DATA_LENGTH];
 | 
			
		||||
    switch (LoraGatewayState)
 | 
			
		||||
    {
 | 
			
		||||
    case LORA_STATE_IDLE:
 | 
			
		||||
        ret = AdapterDeviceRecv(lora_adapter, gateway_recv_data, sizeof(struct LoraDataFormat));
 | 
			
		||||
        if (0 == ret) {
 | 
			
		||||
        memset(lora_recv_data, 0, ADAPTER_LORA_RECV_DATA_LENGTH);
 | 
			
		||||
 | 
			
		||||
        ret = AdapterDeviceRecv(lora_adapter, lora_recv_data, ADAPTER_LORA_RECV_DATA_LENGTH);
 | 
			
		||||
        if (ret <= 0)  {
 | 
			
		||||
            printf("LoraGatewayProcess IDLE recv error.Just return\n");
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        LoraReceiveDataCheck(lora_recv_data, ADAPTER_LORA_RECV_DATA_LENGTH, gateway_recv_data);
 | 
			
		||||
 | 
			
		||||
        if (ADAPTER_LORA_DATA_TYPE_JOIN == gateway_recv_data->data_type) {
 | 
			
		||||
            LoraGatewayState = LORA_JOIN_NET;
 | 
			
		||||
        } else if (ADAPTER_LORA_DATA_TYPE_QUIT == gateway_recv_data->data_type) {
 | 
			
		||||
| 
						 | 
				
			
			@ -516,12 +564,15 @@ int LoraGatewayProcess(struct Adapter *lora_adapter, struct LoraGatewayParam *ga
 | 
			
		|||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ret = AdapterDeviceRecv(lora_adapter, gateway_recv_data, sizeof(struct LoraDataFormat));
 | 
			
		||||
                if (0 == ret) {
 | 
			
		||||
                memset(lora_recv_data, 0, ADAPTER_LORA_RECV_DATA_LENGTH);
 | 
			
		||||
                ret = AdapterDeviceRecv(lora_adapter, lora_recv_data, ADAPTER_LORA_RECV_DATA_LENGTH);
 | 
			
		||||
                if (ret <= 0) {
 | 
			
		||||
                    printf("LoraGatewayProcess recv error.Just return\n");
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                LoraReceiveDataCheck(lora_recv_data, ADAPTER_LORA_RECV_DATA_LENGTH, gateway_recv_data);
 | 
			
		||||
 | 
			
		||||
                if (ADAPTER_LORA_DATA_TYPE_JOIN == gateway_recv_data->data_type) {
 | 
			
		||||
                    LoraGatewayState = LORA_JOIN_NET;
 | 
			
		||||
                } else if (ADAPTER_LORA_DATA_TYPE_QUIT == gateway_recv_data->data_type) {
 | 
			
		||||
| 
						 | 
				
			
			@ -754,19 +805,30 @@ int AdapterLoraTest(void)
 | 
			
		|||
 | 
			
		||||
    //create lora gateway task
 | 
			
		||||
#ifdef AS_LORA_GATEWAY_ROLE
 | 
			
		||||
#ifdef ADD_NUTTX_FETURES
 | 
			
		||||
    pthread_attr_t lora_gateway_attr = PTHREAD_ATTR_INITIALIZER;
 | 
			
		||||
    lora_gateway_attr.priority = 20;
 | 
			
		||||
    lora_gateway_attr.stacksize = 2048;
 | 
			
		||||
#else
 | 
			
		||||
    pthread_attr_t lora_gateway_attr;
 | 
			
		||||
    lora_gateway_attr.schedparam.sched_priority = 20;
 | 
			
		||||
    lora_gateway_attr.stacksize = 2048;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    PrivTaskCreate(&lora_gateway_task, &lora_gateway_attr, &LoraGatewayTask, (void *)adapter);
 | 
			
		||||
    PrivTaskStartup(&lora_gateway_task);
 | 
			
		||||
 | 
			
		||||
#else //AS_LORA_CLIENT_ROLE
 | 
			
		||||
    //create lora client task
 | 
			
		||||
#ifdef ADD_NUTTX_FETURES
 | 
			
		||||
    pthread_attr_t lora_client_attr = PTHREAD_ATTR_INITIALIZER;
 | 
			
		||||
    lora_client_attr.priority = 20;
 | 
			
		||||
    lora_client_attr.stacksize = 2048;
 | 
			
		||||
#else
 | 
			
		||||
    pthread_attr_t lora_client_attr;
 | 
			
		||||
    lora_client_attr.schedparam.sched_priority = 20;
 | 
			
		||||
    lora_client_attr.stacksize = 2048;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
    //create lora client task
 | 
			
		||||
    PrivTaskCreate(&lora_client_data_task, &lora_client_attr, &LoraClientDataTask, (void *)adapter);
 | 
			
		||||
    PrivTaskStartup(&lora_client_data_task);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -778,4 +840,7 @@ int AdapterLoraTest(void)
 | 
			
		|||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
#ifdef ADD_XIZI_FETURES
 | 
			
		||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN, AdapterLoraTest, AdapterLoraTest, show adapter lora information);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,9 @@ if ADD_XIZI_FETURES
 | 
			
		|||
endif
 | 
			
		||||
 | 
			
		||||
if ADD_NUTTX_FETURES
 | 
			
		||||
        config ADAPTER_SX1278_DRIVER
 | 
			
		||||
        string "SX1278 device spi driver path"
 | 
			
		||||
        default "/dev/spi2_lora"
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
############################################################################
 | 
			
		||||
# APP_Framework/Framework/connection/lora/sx1278/Make.defs
 | 
			
		||||
############################################################################
 | 
			
		||||
ifneq ($(CONFIG_ADAPTER_LORA_SX1278),)
 | 
			
		||||
CONFIGURED_APPS += $(APPDIR)/../../../APP_Framework/Framework/connection/lora/sx1278
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,13 @@
 | 
			
		|||
SRC_FILES := sx1278.c
 | 
			
		||||
include $(KERNEL_ROOT)/.config
 | 
			
		||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
 | 
			
		||||
    include $(APPDIR)/Make.defs
 | 
			
		||||
    CSRCS += sx1278.c
 | 
			
		||||
    include $(APPDIR)/Application.mk
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
 | 
			
		||||
    SRC_FILES := sx1278.c
 | 
			
		||||
    include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,32 @@
 | 
			
		|||
 | 
			
		||||
#include <adapter.h>
 | 
			
		||||
 | 
			
		||||
#ifdef ADD_NUTTX_FETURES
 | 
			
		||||
 /**
 | 
			
		||||
 * @description: Sx127x_Nuttx_Write function for nuttx
 | 
			
		||||
 * @param fd - file descriptor to write to
 | 
			
		||||
 * @param buf - Data to write
 | 
			
		||||
 * @param buf - Length of data to write
 | 
			
		||||
 * @return On success, the number of bytes written are returned (zero indicates nothing was written). On error, -1 is returned.
 | 
			
		||||
 */
 | 
			
		||||
static int Sx127x_Nuttx_Write(int fd, const void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    unsigned char *buffer = (unsigned char*)PrivMalloc(256);
 | 
			
		||||
    if (!buffer)
 | 
			
		||||
    {
 | 
			
		||||
      printf("failed to allocate buffer\n");
 | 
			
		||||
    }
 | 
			
		||||
    memset(buffer, 0, 256);
 | 
			
		||||
    memcpy(buffer,(unsigned char *)buf,len);
 | 
			
		||||
 | 
			
		||||
    ret = PrivWrite(fd, buffer, len);
 | 
			
		||||
    PrivFree(buffer);
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Open SX1278 spi function
 | 
			
		||||
 * @param adapter - Lora device pointer
 | 
			
		||||
| 
						 | 
				
			
			@ -47,9 +73,14 @@ static int Sx1278Open(struct Adapter *adapter)
 | 
			
		|||
static int Sx1278Close(struct Adapter *adapter)
 | 
			
		||||
{
 | 
			
		||||
    /*step1: close sx1278 spi port*/
 | 
			
		||||
    PrivClose(adapter->fd);
 | 
			
		||||
    int ret;
 | 
			
		||||
    ret = PrivClose(adapter->fd);
 | 
			
		||||
    if(ret < 0){
 | 
			
		||||
        printf("Sx1278 close failed: %d!\n", ret);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ADAPTER_DEBUG("Sx1278Close done\n");
 | 
			
		||||
    ADAPTER_DEBUG("Sx1278 Close done\n");
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -73,13 +104,30 @@ static int Sx1278Ioctl(struct Adapter *adapter, int cmd, void *args)
 | 
			
		|||
 * @param priv_net_group - priv_net_group params
 | 
			
		||||
 * @return success: 0, failure: -1
 | 
			
		||||
 */
 | 
			
		||||
#ifdef ADD_NUTTX_FETURES
 | 
			
		||||
static int Sx1278Join(struct Adapter *adapter, unsigned char *priv_net_group)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    ret = Sx127x_Nuttx_Write(adapter->fd, (void *)priv_net_group, 144);
 | 
			
		||||
    if(ret < 0){
 | 
			
		||||
        printf("Sx1278 Join net group failed: %d!\n", ret);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    PrivWrite(adapter->fd, (void *)priv_net_group, 144);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
static int Sx1278Join(struct Adapter *adapter, unsigned char *priv_net_group)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    ret = PrivWrite(adapter->fd, (void *)priv_net_group, 144);
 | 
			
		||||
    if(ret < 0){
 | 
			
		||||
        printf("Sx1278 Join net group failed: %d!\n", ret);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: SX1278 send data function
 | 
			
		||||
| 
						 | 
				
			
			@ -88,11 +136,28 @@ static int Sx1278Join(struct Adapter *adapter, unsigned char *priv_net_group)
 | 
			
		|||
 * @param len - data len
 | 
			
		||||
 * @return success: 0, failure: -1
 | 
			
		||||
 */
 | 
			
		||||
#ifdef ADD_NUTTX_FETURES
 | 
			
		||||
static int Sx1278Send(struct Adapter *adapter, const void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    PrivWrite(adapter->fd, buf, len);
 | 
			
		||||
    return 0;
 | 
			
		||||
    int ret;
 | 
			
		||||
    ret = Sx127x_Nuttx_Write(adapter->fd, buf, len);
 | 
			
		||||
    if(ret < 0){
 | 
			
		||||
        printf("send failed %d!\n", ret);
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
static int Sx1278Send(struct Adapter *adapter, const void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    ret = PrivWrite(adapter->fd, buf, len);
 | 
			
		||||
    if(ret < 0){
 | 
			
		||||
        printf("send failed %d!\n", ret);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: SX1278 receive data function 
 | 
			
		||||
| 
						 | 
				
			
			@ -101,10 +166,25 @@ static int Sx1278Send(struct Adapter *adapter, const void *buf, size_t len)
 | 
			
		|||
 * @param len - data len
 | 
			
		||||
 * @return success: 0, failure: -1
 | 
			
		||||
 */
 | 
			
		||||
#ifdef ADD_NUTTX_FETURES
 | 
			
		||||
static int Sx1278Recv(struct Adapter *adapter, void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    struct sx127x_read_hdr_s recv_data;
 | 
			
		||||
    ret = read(adapter->fd, &recv_data, sizeof(struct sx127x_read_hdr_s));
 | 
			
		||||
    if (ret <= 0){
 | 
			
		||||
        printf("Read failed %d!\n", ret);
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
    memcpy((uint8 *)buf, (uint8 *)(&recv_data), len);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
static int Sx1278Recv(struct Adapter *adapter, void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    return PrivRead(adapter->fd, buf, len);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: SX1278 quit lora net group function
 | 
			
		||||
| 
						 | 
				
			
			@ -112,12 +192,30 @@ static int Sx1278Recv(struct Adapter *adapter, void *buf, size_t len)
 | 
			
		|||
 * @param priv_net_group - priv_net_group params
 | 
			
		||||
 * @return success: 0, failure: -1
 | 
			
		||||
 */
 | 
			
		||||
#ifdef ADD_NUTTX_FETURES
 | 
			
		||||
static int Sx1278Quit(struct Adapter *adapter, unsigned char *priv_net_group)
 | 
			
		||||
{
 | 
			
		||||
    PrivWrite(adapter->fd, (void *)priv_net_group, 144);
 | 
			
		||||
    int ret;
 | 
			
		||||
    ret = Sx127x_Nuttx_Write(adapter->fd, (void *)priv_net_group, 144);
 | 
			
		||||
    if(ret < 0){
 | 
			
		||||
        printf("Sx1278 quit net group failed %d!\n", ret);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
static int Sx1278Quit(struct Adapter *adapter, unsigned char *priv_net_group)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    ret = PrivWrite(adapter->fd, (void *)priv_net_group, 144);
 | 
			
		||||
    if(ret < 0){
 | 
			
		||||
        printf("Sx1278 quit net group failed %d!\n", ret);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static const struct PrivProtocolDone sx1278_done = 
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,3 @@
 | 
			
		|||
SRC_FILES := ua_data.c open62541.c ua_client.c ua_server.c
 | 
			
		||||
SRC_FILES := ua_data.c open62541.c ua_client.c ua_server.c ua_api.c ua_test.c
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,18 +15,6 @@
 | 
			
		|||
 * A PARTICULAR PURPOSE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2021 AIIT XUOS Lab
 | 
			
		||||
 * XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
 * You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
 *        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
 * See the Mulan PSL v2 for more details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file open62541.c
 | 
			
		||||
 * @brief Support OPCUA protocol
 | 
			
		||||
| 
						 | 
				
			
			@ -44256,7 +44244,7 @@ UA_Client_run_iterate(UA_Client *client, UA_UInt32 timeout) {
 | 
			
		|||
       client->sessionState < UA_SESSIONSTATE_ACTIVATED) {
 | 
			
		||||
        retval = connectIterate(client, timeout);
 | 
			
		||||
        notifyClientState(client);
 | 
			
		||||
        lw_print("lw: [%s] ret %d timeout %d state %d ch %d\n", __func__, retval, timeout,
 | 
			
		||||
        ua_print("lw: [%s] ret %d timeout %d state %d ch %d\n", __func__, retval, timeout,
 | 
			
		||||
            client->sessionState, client->channel.state);
 | 
			
		||||
        return retval;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -45299,7 +45287,7 @@ connectIterate(UA_Client *client, UA_UInt32 timeout) {
 | 
			
		|||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lw_print("lw: [%s] sess %d conn %d\n", __func__, client->sessionState, client->connectStatus);
 | 
			
		||||
    ua_print("ua: [%s] sess %d conn %d\n", __func__, client->sessionState, client->connectStatus);
 | 
			
		||||
    return client->connectStatus;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,98 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2021 AIIT XUOS Lab
 | 
			
		||||
* XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file ua_api.c
 | 
			
		||||
 * @brief Demo for OpcUa function
 | 
			
		||||
 * @version 1.0
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.11.11
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "open62541.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "ua_api.h"
 | 
			
		||||
 | 
			
		||||
int ua_open(void *dev)
 | 
			
		||||
{
 | 
			
		||||
    UaParamType *param = (UaParamType *)dev;
 | 
			
		||||
 | 
			
		||||
    param->client = UA_Client_new();
 | 
			
		||||
 | 
			
		||||
    ua_pr_info("ua: [%s] start ...\n", __func__);
 | 
			
		||||
 | 
			
		||||
    if (param->client == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("ua: [%s] tcp client null\n", __func__);
 | 
			
		||||
        return EEMPTY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UA_ClientConfig *config = UA_Client_getConfig(param->client);
 | 
			
		||||
    UA_ClientConfig_setDefault(config);
 | 
			
		||||
 | 
			
		||||
    ua_pr_info("ua: [%s] %d %s\n", __func__, strlen(param->ua_remote_ip), param->ua_remote_ip);
 | 
			
		||||
 | 
			
		||||
    UA_StatusCode retval = UA_Client_connect(param->client, param->ua_remote_ip);
 | 
			
		||||
    if(retval != UA_STATUSCODE_GOOD) {
 | 
			
		||||
        ua_pr_info("ua: [%s] deleted ret %x!\n", __func__, retval);
 | 
			
		||||
        return (int)retval;
 | 
			
		||||
    }
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ua_close(void *dev)
 | 
			
		||||
{
 | 
			
		||||
    UaParamType *param = (UaParamType *)dev;
 | 
			
		||||
    UA_Client_disconnect(param->client);
 | 
			
		||||
    UA_Client_delete(param->client); /* Disconnects the client internally */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ua_read(void *dev, void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    UaParamType *param = (UaParamType *)dev;
 | 
			
		||||
    switch(param->act)
 | 
			
		||||
    {
 | 
			
		||||
        case UA_ACT_ATTR:
 | 
			
		||||
            ua_read_nodeid_value(param->client, param->ua_id, buf);
 | 
			
		||||
            break;
 | 
			
		||||
        case UA_ACT_OBJ:
 | 
			
		||||
            ua_test_browser_objects(param->client);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ua_write(void *dev, const void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    UaParamType *param = (UaParamType *)dev;
 | 
			
		||||
 | 
			
		||||
    switch(param->act)
 | 
			
		||||
    {
 | 
			
		||||
        case UA_ACT_ATTR:
 | 
			
		||||
            ua_write_nodeid_value(param->client, param->ua_id, (char *)buf);
 | 
			
		||||
            break;
 | 
			
		||||
        case UA_ACT_OBJ:
 | 
			
		||||
            ua_test_browser_objects(param->client);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ua_ioctl(void *dev, int cmd, void *arg)
 | 
			
		||||
{
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -9,23 +9,64 @@
 | 
			
		|||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file ua_api.h
 | 
			
		||||
 * @brief API for OpcUa function
 | 
			
		||||
 * @version 1.0
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.11.11
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __UA_API_H__
 | 
			
		||||
#define __UA_API_H__
 | 
			
		||||
 | 
			
		||||
#include "open62541.h"
 | 
			
		||||
 | 
			
		||||
#define OPC_SERVER "opc.tcp://192.168.250.5:4840"
 | 
			
		||||
#define UA_DEV_IP_LEN 48
 | 
			
		||||
#define UA_NODE_LEN 32
 | 
			
		||||
 | 
			
		||||
#define ua_print //printf
 | 
			
		||||
#define ua_trace() //printf("ua: [%s] line %d checked!\n", __func__, __LINE__)
 | 
			
		||||
enum UaAction_e
 | 
			
		||||
{
 | 
			
		||||
    UA_ACT_ATTR,
 | 
			
		||||
    UA_ACT_OBJ,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct UaParam
 | 
			
		||||
{
 | 
			
		||||
    enum UaAction_e act;
 | 
			
		||||
    UA_NodeId ua_id;
 | 
			
		||||
    char ua_remote_ip[UA_DEV_IP_LEN];
 | 
			
		||||
    char ua_node[UA_NODE_LEN];
 | 
			
		||||
    UA_Client *client;
 | 
			
		||||
}UaParamType;
 | 
			
		||||
 | 
			
		||||
#define ua_print //KPrintf
 | 
			
		||||
#define ua_trace() //KPrintf("ua: [%s] line %d checked!\n", __func__, __LINE__)
 | 
			
		||||
#define ua_pr_info KPrintf
 | 
			
		||||
#define ua_debug
 | 
			
		||||
#define ua_debug //KPrintf
 | 
			
		||||
 | 
			
		||||
extern const char *opc_server_url;
 | 
			
		||||
extern char test_ua_ip[];
 | 
			
		||||
 | 
			
		||||
int ua_server_connect(void);
 | 
			
		||||
int ua_get_server_info(UA_Client *client);
 | 
			
		||||
void ua_browser_objects(UA_Client *client);
 | 
			
		||||
void ua_browser_nodes(UA_Client *client);
 | 
			
		||||
void ua_browser_id(UA_Client *client, UA_NodeId id);
 | 
			
		||||
void ua_read_time(UA_Client *client);
 | 
			
		||||
int16 ua_test(void);
 | 
			
		||||
void ua_add_nodes(UA_Client *client);
 | 
			
		||||
 | 
			
		||||
int ua_open(void *dev); // open and connect PLC device
 | 
			
		||||
void ua_close(void* dev); // close and disconnect PLC device
 | 
			
		||||
int ua_read(void* dev, void *buf, size_t len); // read data from PLC
 | 
			
		||||
int ua_write(void* dev, const void *buf, size_t len); // write data from PLC
 | 
			
		||||
int ua_ioctl(void* dev, int cmd, void *arg); // send control command to PLC
 | 
			
		||||
 | 
			
		||||
char *ua_get_nodeid_str(UA_NodeId *node_id);
 | 
			
		||||
void ua_read_nodeid_value(UA_Client *client, UA_NodeId id, UA_Int32 *value);
 | 
			
		||||
void ua_write_nodeid_value(UA_Client *client, UA_NodeId id, char* value);
 | 
			
		||||
void ua_test_attr(UA_Client *client);
 | 
			
		||||
UA_StatusCode ua_read_array_value(UA_Client *client, int array_size, UA_ReadValueId *array);
 | 
			
		||||
void ua_test_browser_objects(UA_Client *client);
 | 
			
		||||
int ua_test_interact_server(UA_Client *client);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,185 +10,367 @@
 | 
			
		|||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "open62541.h"
 | 
			
		||||
/**
 | 
			
		||||
 * @file ua_client.c
 | 
			
		||||
 * @brief Client for OpcUa function
 | 
			
		||||
 * @version 1.0
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.11.11
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "open62541.h"
 | 
			
		||||
#include "ua_api.h"
 | 
			
		||||
 | 
			
		||||
#define UA_RESPONSE_TIMEOUT 10000
 | 
			
		||||
 | 
			
		||||
const char *opc_server_url = {"opc.tcp://192.168.250.2:4840"};
 | 
			
		||||
 | 
			
		||||
#ifdef UA_ENABLE_SUBSCRIPTIONS
 | 
			
		||||
static void handler_TheAnswerChanged(UA_Client *client, UA_UInt32 subId, void *subContext,
 | 
			
		||||
                         UA_UInt32 monId, void *monContext, UA_DataValue *value)
 | 
			
		||||
static void handler_TheAnswerChanged(UA_Client* client, UA_UInt32 subId, void* subContext,
 | 
			
		||||
                                     UA_UInt32 monId, void* monContext, UA_DataValue* value)
 | 
			
		||||
{
 | 
			
		||||
    ua_print("The Answer has changed!\n");
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle)
 | 
			
		||||
static UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void* handle)
 | 
			
		||||
{
 | 
			
		||||
    if(isInverse)
 | 
			
		||||
    {
 | 
			
		||||
        return UA_STATUSCODE_GOOD;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UA_NodeId *parent = (UA_NodeId *)handle;
 | 
			
		||||
    UA_NodeId* parent = (UA_NodeId*)handle;
 | 
			
		||||
    ua_pr_info("%d, %d --- %d ---> NodeId %d, %d\n",
 | 
			
		||||
           parent->namespaceIndex, parent->identifier.numeric,
 | 
			
		||||
           referenceTypeId.identifier.numeric, childId.namespaceIndex,
 | 
			
		||||
           childId.identifier.numeric);
 | 
			
		||||
 | 
			
		||||
               parent->namespaceIndex, parent->identifier.numeric,
 | 
			
		||||
               referenceTypeId.identifier.numeric, childId.namespaceIndex,
 | 
			
		||||
               childId.identifier.numeric);
 | 
			
		||||
    return UA_STATUSCODE_GOOD;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ua_get_points(UA_Client *client)
 | 
			
		||||
int ua_get_points(UA_Client* client)
 | 
			
		||||
{
 | 
			
		||||
    /* Listing endpoints */
 | 
			
		||||
    UA_EndpointDescription* endpointArray = NULL;
 | 
			
		||||
    size_t endpointArraySize = 0;
 | 
			
		||||
    UA_StatusCode retval = UA_Client_getEndpoints(client, OPC_SERVER,
 | 
			
		||||
    UA_StatusCode ret = UA_Client_getEndpoints(client, opc_server_url,
 | 
			
		||||
                                                  &endpointArraySize, &endpointArray);
 | 
			
		||||
    if(retval != UA_STATUSCODE_GOOD)
 | 
			
		||||
 | 
			
		||||
    if(ret != UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        UA_Array_delete(endpointArray, endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
 | 
			
		||||
        return EXIT_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ua_print("%i endpoints found\n", (int)endpointArraySize);
 | 
			
		||||
    for(size_t i=0;i<endpointArraySize;i++)
 | 
			
		||||
 | 
			
		||||
    for(size_t i=0; i<endpointArraySize; i++)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("URL of endpoint %i is %.*s\n", (int)i,
 | 
			
		||||
               (int)endpointArray[i].endpointUrl.length,
 | 
			
		||||
               endpointArray[i].endpointUrl.data);
 | 
			
		||||
                 (int)endpointArray[i].endpointUrl.length,
 | 
			
		||||
                 endpointArray[i].endpointUrl.data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UA_Array_delete(endpointArray,endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
 | 
			
		||||
    return EXIT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ua_browser_objects(UA_Client *client)
 | 
			
		||||
void ua_print_value(UA_Variant* val)
 | 
			
		||||
{
 | 
			
		||||
    /* Browse some objects */
 | 
			
		||||
    ua_pr_info("Browsing nodes in objects folder:\n");
 | 
			
		||||
    if(val->type == &UA_TYPES[UA_TYPES_LOCALIZEDTEXT])
 | 
			
		||||
    {
 | 
			
		||||
        UA_LocalizedText* ptr = (UA_LocalizedText*)val->data;
 | 
			
		||||
        ua_pr_info("%.*s (Text)\n", ptr->text.length, ptr->text.data);
 | 
			
		||||
    }
 | 
			
		||||
    else if(val->type == &UA_TYPES[UA_TYPES_UINT32])
 | 
			
		||||
    {
 | 
			
		||||
        UA_UInt32* ptr = (UA_UInt32*)val->data;
 | 
			
		||||
        ua_pr_info("%d (UInt32)\n", *ptr);
 | 
			
		||||
    }
 | 
			
		||||
    else if(val->type == &UA_TYPES[UA_TYPES_BOOLEAN])
 | 
			
		||||
    {
 | 
			
		||||
        UA_Boolean* ptr = (UA_Boolean*)val->data;
 | 
			
		||||
        ua_pr_info("%i (BOOL)\n", *ptr);
 | 
			
		||||
    }
 | 
			
		||||
    else if(val->type == &UA_TYPES[UA_TYPES_INT32])
 | 
			
		||||
    {
 | 
			
		||||
        UA_Int32* ptr = (UA_Int32*)val->data;
 | 
			
		||||
        ua_pr_info("%d (Int32)\n", *ptr);
 | 
			
		||||
    }
 | 
			
		||||
    else if(val->type == &UA_TYPES[UA_TYPES_INT16])
 | 
			
		||||
    {
 | 
			
		||||
        UA_Int16* ptr = (UA_Int16*)val->data;
 | 
			
		||||
        ua_pr_info("%d (Int16)\n", *ptr);
 | 
			
		||||
    }
 | 
			
		||||
    else if(val->type == &UA_TYPES[UA_TYPES_STRING])
 | 
			
		||||
    {
 | 
			
		||||
        UA_String* ptr = (UA_String*)val->data;
 | 
			
		||||
        ua_pr_info("%*.s (String)\n", ptr->length, ptr->data);
 | 
			
		||||
    }
 | 
			
		||||
    else if(val->type == &UA_TYPES[UA_TYPES_DATETIME])
 | 
			
		||||
    {
 | 
			
		||||
        UA_DateTime* ptr = (UA_DateTime*)val->data;
 | 
			
		||||
        UA_DateTimeStruct dts = UA_DateTime_toStruct(*ptr);
 | 
			
		||||
        ua_pr_info("%d-%d-%d %d:%d:%d.%03d (Time)\n",
 | 
			
		||||
                   dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    UA_BrowseRequest bReq;
 | 
			
		||||
    UA_BrowseRequest_init(&bReq);
 | 
			
		||||
char *ua_get_nodeid_str(UA_NodeId *node_id)
 | 
			
		||||
{
 | 
			
		||||
    static char nodeid_str[UA_NODE_LEN] = {0};
 | 
			
		||||
 | 
			
		||||
    bReq.requestedMaxReferencesPerNode = 0;
 | 
			
		||||
    bReq.nodesToBrowse = UA_BrowseDescription_new();
 | 
			
		||||
    bReq.nodesToBrowseSize = 1;
 | 
			
		||||
    bReq.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); /* browse objects folder */
 | 
			
		||||
    bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; /* return everything */
 | 
			
		||||
    switch(node_id->identifierType)
 | 
			
		||||
    {
 | 
			
		||||
        case UA_NODEIDTYPE_NUMERIC:
 | 
			
		||||
            snprintf(nodeid_str, UA_NODE_LEN, "n%d,%d", node_id->namespaceIndex, node_id->identifier.numeric);
 | 
			
		||||
            break;
 | 
			
		||||
        case UA_NODEIDTYPE_STRING:
 | 
			
		||||
            snprintf(nodeid_str, UA_NODE_LEN, "n%d,%.*s", node_id->namespaceIndex, node_id->identifier.string.length,
 | 
			
		||||
                node_id->identifier.string.data);
 | 
			
		||||
            break;
 | 
			
		||||
        case UA_NODEIDTYPE_BYTESTRING:
 | 
			
		||||
            snprintf(nodeid_str, UA_NODE_LEN, "n%d,%s", node_id->namespaceIndex, node_id->identifier.byteString.data);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    return nodeid_str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    UA_BrowseResponse bResp = UA_Client_Service_browse(client, bReq);
 | 
			
		||||
void ua_print_nodeid(UA_NodeId *node_id)
 | 
			
		||||
{
 | 
			
		||||
    switch(node_id->identifierType)
 | 
			
		||||
    {
 | 
			
		||||
        case UA_NODEIDTYPE_NUMERIC:
 | 
			
		||||
            ua_pr_info(" NodeID n%d,%d ", node_id->namespaceIndex, node_id->identifier.numeric);
 | 
			
		||||
            break;
 | 
			
		||||
        case UA_NODEIDTYPE_STRING:
 | 
			
		||||
            ua_pr_info(" NodeID n%d,%.*s ", node_id->namespaceIndex, node_id->identifier.string.length,
 | 
			
		||||
                node_id->identifier.string.data);
 | 
			
		||||
            break;
 | 
			
		||||
        case UA_NODEIDTYPE_BYTESTRING:
 | 
			
		||||
            ua_pr_info(" NodeID n%d,%s ", node_id->namespaceIndex, node_id->identifier.byteString.data);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ua_print_object(UA_BrowseResponse* res)
 | 
			
		||||
{
 | 
			
		||||
    ua_pr_info("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME");
 | 
			
		||||
 | 
			
		||||
    for(size_t i = 0; i < bResp.resultsSize; ++i)
 | 
			
		||||
    for(size_t i = 0; i < res->resultsSize; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        for(size_t j = 0; j < bResp.results[i].referencesSize; ++j)
 | 
			
		||||
        for(size_t j = 0; j < res->results[i].referencesSize; ++j)
 | 
			
		||||
        {
 | 
			
		||||
            UA_ReferenceDescription *ref = &(bResp.results[i].references[j]);
 | 
			
		||||
            UA_ReferenceDescription* ref = &(res->results[i].references[j]);
 | 
			
		||||
 | 
			
		||||
            if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC)
 | 
			
		||||
            {
 | 
			
		||||
                ua_pr_info("%-9d %-16d %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex,
 | 
			
		||||
                       ref->nodeId.nodeId.identifier.numeric, (int)ref->browseName.name.length,
 | 
			
		||||
                       ref->browseName.name.data, (int)ref->displayName.text.length,
 | 
			
		||||
                       ref->displayName.text.data);
 | 
			
		||||
                           ref->nodeId.nodeId.identifier.numeric, (int)ref->browseName.name.length,
 | 
			
		||||
                           ref->browseName.name.data, (int)ref->displayName.text.length,
 | 
			
		||||
                           ref->displayName.text.data);
 | 
			
		||||
            }
 | 
			
		||||
            else if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_STRING)
 | 
			
		||||
            {
 | 
			
		||||
                ua_pr_info("%-9d %-16.*s %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex,
 | 
			
		||||
                       (int)ref->nodeId.nodeId.identifier.string.length,
 | 
			
		||||
                       ref->nodeId.nodeId.identifier.string.data,
 | 
			
		||||
                       (int)ref->browseName.name.length, ref->browseName.name.data,
 | 
			
		||||
                       (int)ref->displayName.text.length, ref->displayName.text.data);
 | 
			
		||||
                           (int)ref->nodeId.nodeId.identifier.string.length,
 | 
			
		||||
                           ref->nodeId.nodeId.identifier.string.data,
 | 
			
		||||
                           (int)ref->browseName.name.length, ref->browseName.name.data,
 | 
			
		||||
                           (int)ref->displayName.text.length, ref->displayName.text.data);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* TODO: distinguish further types */
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ua_pr_info("\n");
 | 
			
		||||
    UA_BrowseRequest_clear(&bReq);
 | 
			
		||||
    UA_BrowseResponse_clear(&bResp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ua_browser_nodes(UA_Client *client)
 | 
			
		||||
UA_StatusCode ua_read_array_value(UA_Client* client, int array_size, UA_ReadValueId* array)
 | 
			
		||||
{
 | 
			
		||||
    /* Same thing, this time using the node iterator... */
 | 
			
		||||
    UA_NodeId *parent = UA_NodeId_new();
 | 
			
		||||
    UA_ReadRequest request;
 | 
			
		||||
    UA_ReadRequest_init(&request);
 | 
			
		||||
    request.nodesToRead = array;
 | 
			
		||||
    request.nodesToReadSize = array_size;
 | 
			
		||||
    UA_ReadResponse response = UA_Client_Service_read(client, request);
 | 
			
		||||
 | 
			
		||||
    if((response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
 | 
			
		||||
            || (response.resultsSize != array_size))
 | 
			
		||||
    {
 | 
			
		||||
        UA_ReadResponse_clear(&response);
 | 
			
		||||
        ua_pr_info("ua: [%s] read failed 0x%x\n", __func__,
 | 
			
		||||
                   response.responseHeader.serviceResult);
 | 
			
		||||
        return UA_STATUSCODE_BADUNEXPECTEDERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UA_StatusCode* arr_ret = malloc(array_size * sizeof(UA_StatusCode));
 | 
			
		||||
 | 
			
		||||
    for(int i = 0; i < array_size; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        if((response.results[i].status == UA_STATUSCODE_GOOD)
 | 
			
		||||
                && (response.results[i].hasValue))
 | 
			
		||||
        {
 | 
			
		||||
            ua_pr_info("node %s: ", ua_get_nodeid_str(&array[i].nodeId));
 | 
			
		||||
            ua_print_value(&response.results[i].value);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    ua_pr_info("\n");
 | 
			
		||||
 | 
			
		||||
    free(arr_ret);
 | 
			
		||||
    UA_ReadResponse_clear(&response);
 | 
			
		||||
    return UA_STATUSCODE_GOOD;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ua_browser_id(UA_Client* client, UA_NodeId id)
 | 
			
		||||
{
 | 
			
		||||
    /* Browse some objects */
 | 
			
		||||
    ua_pr_info("Browsing nodes in objects folder:\n");
 | 
			
		||||
    UA_BrowseRequest bReq;
 | 
			
		||||
    UA_BrowseRequest_init(&bReq);
 | 
			
		||||
    bReq.requestedMaxReferencesPerNode = 0;
 | 
			
		||||
    bReq.nodesToBrowse = UA_BrowseDescription_new();
 | 
			
		||||
    bReq.nodesToBrowseSize = 1;
 | 
			
		||||
    bReq.nodesToBrowse[0].nodeId = id; /* browse objects folder */
 | 
			
		||||
    bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; /* return everything */
 | 
			
		||||
    UA_BrowseResponse res = UA_Client_Service_browse(client, bReq);
 | 
			
		||||
    ua_print_object(&res);
 | 
			
		||||
    UA_BrowseResponse_clear(&res);
 | 
			
		||||
//    UA_BrowseRequest_clear(&bReq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ua_browser_nodes(UA_Client* client)
 | 
			
		||||
{
 | 
			
		||||
    UA_NodeId* parent = UA_NodeId_new();
 | 
			
		||||
    *parent = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
 | 
			
		||||
    UA_Client_forEachChildNodeCall(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
 | 
			
		||||
                                   nodeIter, (void *) parent);
 | 
			
		||||
    UA_Client_forEachChildNodeCall(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIter, (void*) parent);
 | 
			
		||||
    UA_NodeId_delete(parent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UA_UInt32 ua_start_sub(UA_Client *client)
 | 
			
		||||
UA_UInt32 ua_start_sub(UA_Client* client, UA_NodeId node_id)
 | 
			
		||||
{
 | 
			
		||||
    /* Create a subscription */
 | 
			
		||||
    UA_CreateSubscriptionRequest request = UA_CreateSubscriptionRequest_default();
 | 
			
		||||
    UA_CreateSubscriptionResponse response = UA_Client_Subscriptions_create(client, request,
 | 
			
		||||
                                                                            NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
    UA_UInt32 subId = response.subscriptionId;
 | 
			
		||||
 | 
			
		||||
    if(response.responseHeader.serviceResult == UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("Create subscription succeeded, id %u\n", subId);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("Create subscription failed, id %u\n", response.responseHeader.serviceResult);
 | 
			
		||||
        return response.responseHeader.serviceResult;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UA_MonitoredItemCreateRequest monRequest =
 | 
			
		||||
        UA_MonitoredItemCreateRequest_default(UA_NODEID_STRING(1, "the.answer"));
 | 
			
		||||
 | 
			
		||||
        UA_MonitoredItemCreateRequest_default(node_id);
 | 
			
		||||
    UA_MonitoredItemCreateResult monResponse =
 | 
			
		||||
    UA_Client_MonitoredItems_createDataChange(client, response.subscriptionId,
 | 
			
		||||
                                              UA_TIMESTAMPSTORETURN_BOTH,
 | 
			
		||||
                                              monRequest, NULL, handler_TheAnswerChanged, NULL);
 | 
			
		||||
    if(monResponse.statusCode == UA_STATUSCODE_GOOD)
 | 
			
		||||
        ua_print("Monitoring 'the.answer', id %u\n", monResponse.monitoredItemId);
 | 
			
		||||
        UA_Client_MonitoredItems_createDataChange(client, response.subscriptionId,
 | 
			
		||||
                                                  UA_TIMESTAMPSTORETURN_BOTH,
 | 
			
		||||
                                                  monRequest, NULL, handler_TheAnswerChanged, NULL);
 | 
			
		||||
 | 
			
		||||
    if(monResponse.statusCode == UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("Monitoring 'the.answer', id %u\n", monResponse.monitoredItemId);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("%s return 0x%x\n", __func__, monResponse.statusCode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* The first publish request should return the initial value of the variable */
 | 
			
		||||
    UA_Client_run_iterate(client, 1000);
 | 
			
		||||
    UA_Client_run_iterate(client, UA_RESPONSE_TIMEOUT);
 | 
			
		||||
    return subId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ua_read_attr(UA_Client *client)
 | 
			
		||||
void ua_write_nodeid_value(UA_Client* client, UA_NodeId id, char* value)
 | 
			
		||||
{
 | 
			
		||||
    /* Read attribute */
 | 
			
		||||
    UA_Int32 value = 0;
 | 
			
		||||
    ua_print("\nReading the value of node (1, \"the.answer\"):\n");
 | 
			
		||||
    UA_Variant *val = UA_Variant_new();
 | 
			
		||||
    UA_StatusCode retval = UA_Client_readValueAttribute(client, UA_NODEID_STRING(1, "the.answer"), val);
 | 
			
		||||
    if(retval == UA_STATUSCODE_GOOD && UA_Variant_isScalar(val) &&
 | 
			
		||||
       val->type == &UA_TYPES[UA_TYPES_INT32]) {
 | 
			
		||||
            value = *(UA_Int32*)val->data;
 | 
			
		||||
            ua_print("the value is: %i\n", value);
 | 
			
		||||
    }
 | 
			
		||||
    UA_Variant_delete(val);
 | 
			
		||||
 | 
			
		||||
    /* Write node attribute */
 | 
			
		||||
    value++;
 | 
			
		||||
    ua_print("\nWriting a value of node (1, \"the.answer\"):\n");
 | 
			
		||||
    UA_Boolean bool_val;
 | 
			
		||||
    uint32_t integer_val;
 | 
			
		||||
    UA_WriteRequest wReq;
 | 
			
		||||
    UA_WriteRequest_init(&wReq);
 | 
			
		||||
 | 
			
		||||
    wReq.nodesToWrite = UA_WriteValue_new();
 | 
			
		||||
    wReq.nodesToWriteSize = 1;
 | 
			
		||||
    wReq.nodesToWrite[0].nodeId = UA_NODEID_STRING_ALLOC(1, "the.answer");
 | 
			
		||||
 | 
			
		||||
    if(strncmp(value, "1b", 2) == 0)
 | 
			
		||||
    {
 | 
			
		||||
        wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
 | 
			
		||||
        bool_val = 1;
 | 
			
		||||
        wReq.nodesToWrite[0].value.value.data = &bool_val;
 | 
			
		||||
    }
 | 
			
		||||
    else if(strncmp(value, "0b", 2) == 0)
 | 
			
		||||
    {
 | 
			
		||||
        wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
 | 
			
		||||
        bool_val = 0;
 | 
			
		||||
        wReq.nodesToWrite[0].value.value.data = &bool_val;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_INT16];
 | 
			
		||||
        sscanf(value, "%d", &integer_val);
 | 
			
		||||
        wReq.nodesToWrite[0].value.value.data = &integer_val;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wReq.nodesToWrite[0].nodeId = id;
 | 
			
		||||
    wReq.nodesToWrite[0].attributeId = UA_ATTRIBUTEID_VALUE;
 | 
			
		||||
    wReq.nodesToWrite[0].value.hasValue = true;
 | 
			
		||||
    wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_INT32];
 | 
			
		||||
    wReq.nodesToWrite[0].value.value.storageType = UA_VARIANT_DATA_NODELETE; /* do not free the integer on deletion */
 | 
			
		||||
    wReq.nodesToWrite[0].value.value.data = &value;
 | 
			
		||||
    UA_WriteResponse wResp = UA_Client_Service_write(client, wReq);
 | 
			
		||||
 | 
			
		||||
    if(wResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD)
 | 
			
		||||
        ua_print("the new value is: %i\n", value);
 | 
			
		||||
    {
 | 
			
		||||
        ua_pr_info("write new value is: %s\n", value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UA_WriteRequest_clear(&wReq);
 | 
			
		||||
    UA_WriteResponse_clear(&wResp);
 | 
			
		||||
 | 
			
		||||
    /* Write node attribute (using the highlevel API) */
 | 
			
		||||
    value++;
 | 
			
		||||
    UA_Variant *myVariant = UA_Variant_new();
 | 
			
		||||
    UA_Variant_setScalarCopy(myVariant, &value, &UA_TYPES[UA_TYPES_INT32]);
 | 
			
		||||
    UA_Client_writeValueAttribute(client, UA_NODEID_STRING(1, "the.answer"), myVariant);
 | 
			
		||||
    UA_Variant_delete(myVariant);
 | 
			
		||||
 | 
			
		||||
//    /* Write node attribute (using the highlevel API) */
 | 
			
		||||
//    value++;
 | 
			
		||||
//    UA_Variant *myVariant = UA_Variant_new();
 | 
			
		||||
//    UA_Variant_setScalarCopy(myVariant, &value, &UA_TYPES[UA_TYPES_INT32]);
 | 
			
		||||
//    UA_Client_writeValueAttribute(client, UA_NODEID_STRING(1, UA_NODE_STR), myVariant);
 | 
			
		||||
//    UA_Variant_delete(myVariant);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ua_call_remote(UA_Client *client)
 | 
			
		||||
/* Read attribute */
 | 
			
		||||
void ua_read_nodeid_value(UA_Client* client, UA_NodeId id, UA_Int32 *value)
 | 
			
		||||
{
 | 
			
		||||
    UA_Variant* val = UA_Variant_new();
 | 
			
		||||
    UA_StatusCode ret = UA_Client_readValueAttribute(client, id, val);
 | 
			
		||||
 | 
			
		||||
    if(ret == UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print_value(val);
 | 
			
		||||
        if(UA_Variant_isScalar(val))
 | 
			
		||||
        {
 | 
			
		||||
            if(val->type == &UA_TYPES[UA_TYPES_BOOLEAN])
 | 
			
		||||
            {
 | 
			
		||||
                *value = *(UA_Boolean *)val->data;
 | 
			
		||||
            }
 | 
			
		||||
            else if(val->type == &UA_TYPES[UA_TYPES_INT32])
 | 
			
		||||
            {
 | 
			
		||||
                *value = *(UA_Int32 *)val->data;
 | 
			
		||||
            }
 | 
			
		||||
            else if(val->type == &UA_TYPES[UA_TYPES_INT16])
 | 
			
		||||
            {
 | 
			
		||||
                *value = *(UA_Int16 *)val->data;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UA_Variant_delete(val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ua_call_remote(UA_Client* client)
 | 
			
		||||
{
 | 
			
		||||
    /* Call a remote method */
 | 
			
		||||
    UA_Variant input;
 | 
			
		||||
| 
						 | 
				
			
			@ -196,24 +378,26 @@ void ua_call_remote(UA_Client *client)
 | 
			
		|||
    UA_Variant_init(&input);
 | 
			
		||||
    UA_Variant_setScalarCopy(&input, &argString, &UA_TYPES[UA_TYPES_STRING]);
 | 
			
		||||
    size_t outputSize;
 | 
			
		||||
    UA_Variant *output;
 | 
			
		||||
    UA_StatusCode retval = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
 | 
			
		||||
                            UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output);
 | 
			
		||||
    if(retval == UA_STATUSCODE_GOOD)
 | 
			
		||||
    UA_Variant* output;
 | 
			
		||||
    UA_StatusCode ret = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
 | 
			
		||||
                                          UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output);
 | 
			
		||||
 | 
			
		||||
    if(ret == UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("Method call was successful, and %lu returned values available.\n",
 | 
			
		||||
               (unsigned long)outputSize);
 | 
			
		||||
                 (unsigned long)outputSize);
 | 
			
		||||
        UA_Array_delete(output, outputSize, &UA_TYPES[UA_TYPES_VARIANT]);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("Method call was unsuccessful, and %x returned values available.\n", retval);
 | 
			
		||||
        ua_print("Method call was unsuccessful, and %x returned values available.\n", ret);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UA_Variant_clear(&input);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void ua_add_nodes(UA_Client *client)
 | 
			
		||||
void ua_add_nodes(UA_Client* client)
 | 
			
		||||
{
 | 
			
		||||
    /* Add new nodes*/
 | 
			
		||||
    /* New ReferenceType */
 | 
			
		||||
| 
						 | 
				
			
			@ -222,43 +406,52 @@ void ua_add_nodes(UA_Client *client)
 | 
			
		|||
    ref_attr.displayName = UA_LOCALIZEDTEXT("en-US", "NewReference");
 | 
			
		||||
    ref_attr.description = UA_LOCALIZEDTEXT("en-US", "References something that might or might not exist");
 | 
			
		||||
    ref_attr.inverseName = UA_LOCALIZEDTEXT("en-US", "IsNewlyReferencedBy");
 | 
			
		||||
    UA_StatusCode retval = UA_Client_addReferenceTypeNode(client,
 | 
			
		||||
                                            UA_NODEID_NUMERIC(1, 12133),
 | 
			
		||||
                                            UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
 | 
			
		||||
                                            UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
 | 
			
		||||
                                            UA_QUALIFIEDNAME(1, "NewReference"),
 | 
			
		||||
                                            ref_attr, &ref_id);
 | 
			
		||||
    if(retval == UA_STATUSCODE_GOOD )
 | 
			
		||||
    UA_StatusCode ret = UA_Client_addReferenceTypeNode(client,
 | 
			
		||||
                                                          UA_NODEID_NUMERIC(1, 12133),
 | 
			
		||||
                                                          UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
 | 
			
		||||
                                                          UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
 | 
			
		||||
                                                          UA_QUALIFIEDNAME(1, "NewReference"),
 | 
			
		||||
                                                          ref_attr, &ref_id);
 | 
			
		||||
 | 
			
		||||
    if(ret == UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("Created 'NewReference' with numeric NodeID %u\n", ref_id.identifier.numeric);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* New ObjectType */
 | 
			
		||||
    UA_NodeId objt_id;
 | 
			
		||||
    UA_ObjectTypeAttributes objt_attr = UA_ObjectTypeAttributes_default;
 | 
			
		||||
    objt_attr.displayName = UA_LOCALIZEDTEXT("en-US", "TheNewObjectType");
 | 
			
		||||
    objt_attr.description = UA_LOCALIZEDTEXT("en-US", "Put innovative description here");
 | 
			
		||||
    retval = UA_Client_addObjectTypeNode(client,
 | 
			
		||||
    ret = UA_Client_addObjectTypeNode(client,
 | 
			
		||||
                                         UA_NODEID_NUMERIC(1, 12134),
 | 
			
		||||
                                         UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
 | 
			
		||||
                                         UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
 | 
			
		||||
                                         UA_QUALIFIEDNAME(1, "NewObjectType"),
 | 
			
		||||
                                         objt_attr, &objt_id);
 | 
			
		||||
    if(retval == UA_STATUSCODE_GOOD)
 | 
			
		||||
 | 
			
		||||
    if(ret == UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("Created 'NewObjectType' with numeric NodeID %u\n", objt_id.identifier.numeric);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* New Object */
 | 
			
		||||
    UA_NodeId obj_id;
 | 
			
		||||
    UA_ObjectAttributes obj_attr = UA_ObjectAttributes_default;
 | 
			
		||||
    obj_attr.displayName = UA_LOCALIZEDTEXT("en-US", "TheNewGreatNode");
 | 
			
		||||
    obj_attr.description = UA_LOCALIZEDTEXT("de-DE", "Hier koennte Ihre Webung stehen!");
 | 
			
		||||
    retval = UA_Client_addObjectNode(client,
 | 
			
		||||
    ret = UA_Client_addObjectNode(client,
 | 
			
		||||
                                     UA_NODEID_NUMERIC(1, 0),
 | 
			
		||||
                                     UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
 | 
			
		||||
                                     UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
 | 
			
		||||
                                     UA_QUALIFIEDNAME(1, "TheGreatNode"),
 | 
			
		||||
                                     UA_NODEID_NUMERIC(1, 12134),
 | 
			
		||||
                                     obj_attr, &obj_id);
 | 
			
		||||
    if(retval == UA_STATUSCODE_GOOD )
 | 
			
		||||
 | 
			
		||||
    if(ret == UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("Created 'NewObject' with numeric NodeID %u\n", obj_id.identifier.numeric);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* New Integer Variable */
 | 
			
		||||
    UA_NodeId var_id;
 | 
			
		||||
| 
						 | 
				
			
			@ -270,68 +463,36 @@ void ua_add_nodes(UA_Client *client)
 | 
			
		|||
    /* This does not copy the value */
 | 
			
		||||
    UA_Variant_setScalar(&var_attr.value, &int_value, &UA_TYPES[UA_TYPES_INT32]);
 | 
			
		||||
    var_attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
 | 
			
		||||
    retval = UA_Client_addVariableNode(client,
 | 
			
		||||
    ret = UA_Client_addVariableNode(client,
 | 
			
		||||
                                       UA_NODEID_NUMERIC(1, 0), // Assign new/random NodeID
 | 
			
		||||
                                       UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
 | 
			
		||||
                                       UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
 | 
			
		||||
                                       UA_QUALIFIEDNAME(0, "VariableNode"),
 | 
			
		||||
                                       UA_NODEID_NULL, // no variable type
 | 
			
		||||
                                       var_attr, &var_id);
 | 
			
		||||
    if(retval == UA_STATUSCODE_GOOD )
 | 
			
		||||
 | 
			
		||||
    if(ret == UA_STATUSCODE_GOOD)
 | 
			
		||||
    {
 | 
			
		||||
        ua_print("Created 'NewVariable' with numeric NodeID %u\n", var_id.identifier.numeric);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ua_get_server_info(UA_Client *client)
 | 
			
		||||
void ua_read_time(UA_Client* client)
 | 
			
		||||
{
 | 
			
		||||
    ua_browser_objects(client);
 | 
			
		||||
 | 
			
		||||
    /* Same thing, this time using the node iterator... */
 | 
			
		||||
    ua_browser_nodes(client);
 | 
			
		||||
 | 
			
		||||
#ifdef UA_ENABLE_SUBSCRIPTIONS
 | 
			
		||||
    UA_Int32 subId = ua_start_sub(client);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    ua_read_attr(client);
 | 
			
		||||
 | 
			
		||||
#ifdef UA_ENABLE_SUBSCRIPTIONS
 | 
			
		||||
    /* Take another look at the.answer */
 | 
			
		||||
    UA_Client_run_iterate(client, 100);
 | 
			
		||||
    /* Delete the subscription */
 | 
			
		||||
    if(UA_Client_Subscriptions_deleteSingle(client, subId) == UA_STATUSCODE_GOOD)
 | 
			
		||||
        ua_print("Subscription removed\n");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef UA_ENABLE_METHODCALLS
 | 
			
		||||
    ua_call_remote(client);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef UA_ENABLE_NODEMANAGEMENT
 | 
			
		||||
    ua_add_nodes(client);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return EXIT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ua_read_time(UA_Client *client)
 | 
			
		||||
{
 | 
			
		||||
    /* Read the value attribute of the node. UA_Client_readValueAttribute is a
 | 
			
		||||
    * wrapper for the raw read service available as UA_Client_Service_read. */
 | 
			
		||||
    UA_Variant value; /* Variants can hold scalar values and arrays of any type */
 | 
			
		||||
    UA_Variant value;
 | 
			
		||||
    UA_Variant_init(&value);
 | 
			
		||||
 | 
			
		||||
    /* NodeId of the variable holding the current time */
 | 
			
		||||
    const UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
 | 
			
		||||
    UA_StatusCode retval = UA_Client_readValueAttribute(client, nodeId, &value);
 | 
			
		||||
    UA_StatusCode ret = UA_Client_readValueAttribute(client, nodeId, &value);
 | 
			
		||||
 | 
			
		||||
    if(retval == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME]))
 | 
			
		||||
    if(ret == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME]))
 | 
			
		||||
    {
 | 
			
		||||
        UA_DateTime raw_date = *(UA_DateTime *) value.data;
 | 
			
		||||
        UA_DateTime raw_date = *(UA_DateTime*) value.data;
 | 
			
		||||
        UA_DateTimeStruct dts = UA_DateTime_toStruct(raw_date);
 | 
			
		||||
        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "date is: %u-%u-%u %u:%u:%u.%03u\n",
 | 
			
		||||
            dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
 | 
			
		||||
        ua_pr_info("date is: %d-%d-%d %d:%d:%d.%03d\n",
 | 
			
		||||
                    dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Clean up */
 | 
			
		||||
    UA_Variant_clear(&value);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,17 +10,85 @@
 | 
			
		|||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file ua_test.c
 | 
			
		||||
 * @brief Test for OpcUa function
 | 
			
		||||
 * @version 1.0
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.11.11
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "open62541.h"
 | 
			
		||||
#include "ua_api.h"
 | 
			
		||||
 | 
			
		||||
//for target NODEID
 | 
			
		||||
#define UA_TEST_BROWSER_NODEID UA_NODEID_STRING(3, "ServerInterfaces")
 | 
			
		||||
#define UA_TEST_BROWSER_NODEID1 UA_NODEID_NUMERIC(4, 1)
 | 
			
		||||
#define UA_TEST_WRITE_NODEID UA_NODEID_NUMERIC(4, 5)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static UA_StatusCode ua_test_read_array(UA_Client *client)
 | 
			
		||||
{
 | 
			
		||||
    const int item_size = 4;
 | 
			
		||||
    UA_ReadValueId test_item[item_size];
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < item_size; i++)
 | 
			
		||||
    {
 | 
			
		||||
        UA_ReadValueId_init(&test_item[i]);
 | 
			
		||||
        test_item[i].attributeId = UA_ATTRIBUTEID_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    test_item[0].nodeId = UA_NODEID_NUMERIC(4, 2);
 | 
			
		||||
    test_item[1].nodeId = UA_NODEID_NUMERIC(4, 3);
 | 
			
		||||
    test_item[2].nodeId = UA_NODEID_NUMERIC(4, 4);
 | 
			
		||||
    test_item[3].nodeId = UA_NODEID_NUMERIC(4, 5);
 | 
			
		||||
 | 
			
		||||
    return ua_read_array_value(client, item_size, test_item);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ua_test_browser_objects(UA_Client *client)
 | 
			
		||||
{
 | 
			
		||||
    UA_NodeId test_id;
 | 
			
		||||
    ua_browser_id(client, UA_TEST_BROWSER_NODEID);
 | 
			
		||||
    ua_browser_id(client, UA_TEST_BROWSER_NODEID1);
 | 
			
		||||
    test_id = UA_TEST_BROWSER_NODEID1;
 | 
			
		||||
    ua_pr_info("Show values in %s:\n", ua_get_nodeid_str(&test_id));
 | 
			
		||||
    ua_test_read_array(client);
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ua_test_write_attr(UA_Client *client)
 | 
			
		||||
{
 | 
			
		||||
    UA_Int32 value;
 | 
			
		||||
    char val_str[UA_NODE_LEN];
 | 
			
		||||
    UA_NodeId id = UA_TEST_WRITE_NODEID;
 | 
			
		||||
 | 
			
		||||
    ua_pr_info("--- Test write %s ---\n", ua_get_nodeid_str(&id));
 | 
			
		||||
    ua_read_nodeid_value(client, id, &value);
 | 
			
		||||
    ua_write_nodeid_value(client, id, itoa(value + 1, val_str, 10));
 | 
			
		||||
    ua_read_nodeid_value(client, id, &value);
 | 
			
		||||
    ua_pr_info("\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ua_test_interact_server(UA_Client *client)
 | 
			
		||||
{
 | 
			
		||||
    ua_read_time(client);
 | 
			
		||||
    ua_test_browser_objects(client);
 | 
			
		||||
    ua_test_write_attr(client);
 | 
			
		||||
    return EXIT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int16 ua_test(void)
 | 
			
		||||
{
 | 
			
		||||
    UA_Client *client = UA_Client_new();
 | 
			
		||||
    UA_StatusCode retval = UA_Client_connect(client, OPC_SERVER);
 | 
			
		||||
    UA_StatusCode retval = UA_Client_connect(client, opc_server_url);
 | 
			
		||||
    if(retval != UA_STATUSCODE_GOOD) {
 | 
			
		||||
        UA_Client_delete(client);
 | 
			
		||||
        return (int)retval;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ua_read_time(client);
 | 
			
		||||
    ua_run_test(client);
 | 
			
		||||
 | 
			
		||||
    /* Clean up */
 | 
			
		||||
    UA_Client_disconnect(client);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
SRC_FILES := plc.c
 | 
			
		||||
SRC_FILES := plc_device.c plc_channel.c plc_driver.c
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,58 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2021 AIIT XUOS Lab
 | 
			
		||||
* XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file plc.c
 | 
			
		||||
 * @brief plc relative activities
 | 
			
		||||
 * @version 1.0
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.12.15
 | 
			
		||||
 */
 | 
			
		||||
#ifdef USING_CONTROL_PLC_OPCUA
 | 
			
		||||
#include "../interoperability/opcua/open62541.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include "plc.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct PlcDevice plc_device;
 | 
			
		||||
 | 
			
		||||
// open and connect PLC device
 | 
			
		||||
void plc_open(struct PlcDevice *pdev)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// close and disconnect PLC device
 | 
			
		||||
void plc_close(struct PlcDevice *pdev)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// read data from PLC
 | 
			
		||||
void plc_read(struct PlcDevice *pdev, void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// write data from PLC
 | 
			
		||||
void plc_write(struct PlcDevice *pdev, const void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// send control command to PLC
 | 
			
		||||
void plc_ioctl(struct PlcDevice *pdev, int cmd, void *arg)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void plc_init(struct PlcDevice *plc_dev)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,538 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2020 AIIT XUOS Lab
 | 
			
		||||
* XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @file plc_ch.c
 | 
			
		||||
* @brief Support channel driver framework provide ch API version 1.0
 | 
			
		||||
* @author AIIT XUOS Lab
 | 
			
		||||
* @date 2021-04-24
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "string.h"
 | 
			
		||||
#include "plc_channel.h"
 | 
			
		||||
#include "plc_device.h"
 | 
			
		||||
#include "transform.h"
 | 
			
		||||
 | 
			
		||||
DoublelistType ch_linklist;
 | 
			
		||||
 | 
			
		||||
/*Create the ch linklist*/
 | 
			
		||||
static void ChannelLinkInit(struct Channel *ch)
 | 
			
		||||
{
 | 
			
		||||
    static uint8 ch_link_flag = RET_FALSE;
 | 
			
		||||
 | 
			
		||||
    if(!ch_link_flag) {
 | 
			
		||||
        AppInitDoubleList(&ch_linklist);
 | 
			
		||||
        ch_link_flag = RET_TRUE;
 | 
			
		||||
        ch->ch_link_flag = RET_TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*Create the driver of the ch linklist*/
 | 
			
		||||
    if(!ch->ch_drvlink_flag) {
 | 
			
		||||
        AppInitDoubleList(&ch->ch_drvlink);
 | 
			
		||||
        ch->ch_drvlink_flag = RET_TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*Create the hardware device of the ch linklist*/
 | 
			
		||||
    if(!ch->ch_devlink_flag) {
 | 
			
		||||
        AppInitDoubleList(&ch->ch_devlink);
 | 
			
		||||
        ch->ch_devlink_flag = RET_TRUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ChannelMatchDrvDev(struct ChDrv *driver, struct ChDev *device)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(driver);
 | 
			
		||||
    CHECK_CH_PARAM(device);
 | 
			
		||||
 | 
			
		||||
    if(!strncmp(driver->owner_ch->ch_name, device->owner_ch->ch_name, NAME_NUM_MAX)) {
 | 
			
		||||
        KPrintf("ChannelMatchDrvDev match successfully, ch name %s\n", driver->owner_ch->ch_name);
 | 
			
		||||
 | 
			
		||||
        driver->private_data = device->private_data;//driver get the device param
 | 
			
		||||
        device->owner_ch->owner_driver = driver;
 | 
			
		||||
        driver->owner_ch->owner_haldev = device;
 | 
			
		||||
 | 
			
		||||
        return EOK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ERROR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to obtain ch for a certain dev if necessary, then configure and init its drv
 | 
			
		||||
* @param ch - ch pointer
 | 
			
		||||
* @param dev - dev pointer
 | 
			
		||||
* @param drv_name - drv name
 | 
			
		||||
* @param config - ChConfigInfo pointer
 | 
			
		||||
* @return successful:EOK,failed:ERROR
 | 
			
		||||
*/
 | 
			
		||||
int DeviceObtainChannel(struct Channel *ch, struct ChDev *dev, const char *drv_name, struct ChConfigInfo *cfg)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(ch);
 | 
			
		||||
    CHECK_CH_PARAM(dev);
 | 
			
		||||
 | 
			
		||||
    int32 ret = EOK;
 | 
			
		||||
 | 
			
		||||
    ret = PrivMutexObtain(&ch->ch_lock);
 | 
			
		||||
    if(EOK != ret) {
 | 
			
		||||
        KPrintf("DevObtainChannel ch_lock error %d!\n", ret);
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(ch->owner_haldev != dev) {
 | 
			
		||||
        struct ChDrv *drv = ChannelFindDriver(ch, drv_name);
 | 
			
		||||
 | 
			
		||||
        cfg->configure_cmd = OPE_CFG;
 | 
			
		||||
        drv->configure(drv, cfg);
 | 
			
		||||
 | 
			
		||||
        cfg->configure_cmd = OPE_INT;
 | 
			
		||||
        drv->configure(drv, cfg);
 | 
			
		||||
 | 
			
		||||
        ch->owner_haldev = dev;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to register ch pointer with linklist
 | 
			
		||||
* @param ch - ch pointer
 | 
			
		||||
* @return successful:EOK,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
int ChannelRegister(struct Channel *ch)
 | 
			
		||||
{
 | 
			
		||||
    int ret = EOK;
 | 
			
		||||
    CHECK_CH_PARAM(ch);
 | 
			
		||||
 | 
			
		||||
    ch->match = ChannelMatchDrvDev;
 | 
			
		||||
 | 
			
		||||
    ChannelLinkInit(ch);
 | 
			
		||||
 | 
			
		||||
    PrivMutexCreate(&ch->ch_lock, NULL);
 | 
			
		||||
 | 
			
		||||
    AppDoubleListInsertNodeAfter(&ch_linklist, &(ch->ch_link));
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to release ch pointer in linklist
 | 
			
		||||
* @param ch - ch pointer
 | 
			
		||||
* @return successful:EOK,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
int ChannelRelease(struct Channel *ch)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(ch);
 | 
			
		||||
 | 
			
		||||
    PrivMutexAbandon(&ch->ch_lock);
 | 
			
		||||
 | 
			
		||||
    ch->ch_cnt = 0;
 | 
			
		||||
    ch->driver_cnt = 0;
 | 
			
		||||
    ch->haldev_cnt = 0;
 | 
			
		||||
 | 
			
		||||
    ch->ch_link_flag = RET_FALSE;
 | 
			
		||||
    ch->ch_drvlink_flag = RET_FALSE;
 | 
			
		||||
    ch->ch_devlink_flag = RET_FALSE;
 | 
			
		||||
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to unregister ch pointer and delete its linklist node
 | 
			
		||||
* @param ch - ch pointer
 | 
			
		||||
* @return successful:EOK,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
int ChannelUnregister(struct Channel *ch)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(ch);
 | 
			
		||||
 | 
			
		||||
    ch->ch_cnt--;
 | 
			
		||||
 | 
			
		||||
    AppDoubleListRmNode(&(ch->ch_link));
 | 
			
		||||
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to register driver pointer to ch pointer
 | 
			
		||||
* @param ch - ch pointer
 | 
			
		||||
* @param driver - driver pointer
 | 
			
		||||
* @return successful:EOK,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
int DriverRegisterToChannel(struct Channel *ch, struct ChDrv *driver)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(ch);
 | 
			
		||||
    CHECK_CH_PARAM(driver);
 | 
			
		||||
 | 
			
		||||
    driver->owner_ch = ch;
 | 
			
		||||
    ch->driver_cnt++;
 | 
			
		||||
 | 
			
		||||
    AppDoubleListInsertNodeAfter(&ch->ch_drvlink, &(driver->driver_link));
 | 
			
		||||
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to register dev pointer to ch pointer
 | 
			
		||||
* @param ch - ch pointer
 | 
			
		||||
* @param device - device pointer
 | 
			
		||||
* @return successful:EOK,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
int DeviceRegisterToChannel(struct Channel *ch, struct ChDev *device)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(ch);
 | 
			
		||||
    CHECK_CH_PARAM(device);
 | 
			
		||||
 | 
			
		||||
    device->owner_ch = ch;
 | 
			
		||||
    ch->haldev_cnt++;
 | 
			
		||||
 | 
			
		||||
    AppDoubleListInsertNodeAfter(&ch->ch_devlink, &(device->dev_link));
 | 
			
		||||
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to delete driver pointer from ch pointer
 | 
			
		||||
* @param ch - ch pointer
 | 
			
		||||
* @param driver - driver pointer
 | 
			
		||||
* @return successful:EOK,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
int DriverDeleteFromChannel(struct Channel *ch, struct ChDrv *driver)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(ch);
 | 
			
		||||
    CHECK_CH_PARAM(driver);
 | 
			
		||||
 | 
			
		||||
    ch->driver_cnt--;
 | 
			
		||||
 | 
			
		||||
    AppDoubleListRmNode(&(driver->driver_link));
 | 
			
		||||
 | 
			
		||||
    free(driver);
 | 
			
		||||
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to delete dev pointer from ch pointer
 | 
			
		||||
* @param ch - ch pointer
 | 
			
		||||
* @param device - device pointer
 | 
			
		||||
* @return successful:EOK,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
int DeviceDeleteFromChannel(struct Channel *ch, struct ChDev *device)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(ch);
 | 
			
		||||
    CHECK_CH_PARAM(device);
 | 
			
		||||
 | 
			
		||||
    ch->haldev_cnt--;
 | 
			
		||||
 | 
			
		||||
    AppDoubleListRmNode(&(device->dev_link));
 | 
			
		||||
 | 
			
		||||
    free(device);
 | 
			
		||||
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to find ch pointer by ch name
 | 
			
		||||
* @param ch_name - ch name
 | 
			
		||||
* @return successful:ch pointer,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
ChannelType ChannelFind(const char *ch_name)
 | 
			
		||||
{
 | 
			
		||||
    struct Channel *ch = NONE;
 | 
			
		||||
 | 
			
		||||
    DoublelistType *node = NONE;
 | 
			
		||||
    DoublelistType *head = &ch_linklist;
 | 
			
		||||
 | 
			
		||||
    for (node = head->node_next; node != head; node = node->node_next)
 | 
			
		||||
    {
 | 
			
		||||
        ch = DOUBLE_LIST_ENTRY(node, struct Channel, ch_link);
 | 
			
		||||
        if(!strcmp(ch->ch_name, ch_name)) {
 | 
			
		||||
            return ch;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    KPrintf("ChannelFind cannot find the %s ch.return NULL\n", ch_name);
 | 
			
		||||
    return NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to find driver pointer of certain ch by driver name
 | 
			
		||||
* @param ch - ch pointer
 | 
			
		||||
* @param driver_name - driver name
 | 
			
		||||
* @return successful:EOK,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
ChDrvType ChannelFindDriver(struct Channel *ch, const char *driver_name)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(ch);
 | 
			
		||||
    struct ChDrv *driver = NONE;
 | 
			
		||||
 | 
			
		||||
    DoublelistType *node = NONE;
 | 
			
		||||
    DoublelistType *head = &ch->ch_drvlink;
 | 
			
		||||
 | 
			
		||||
    for (node = head->node_next; node != head; node = node->node_next)
 | 
			
		||||
    {
 | 
			
		||||
        driver = DOUBLE_LIST_ENTRY(node, struct ChDrv, driver_link);
 | 
			
		||||
        if(!strcmp(driver->drv_name, driver_name)) {
 | 
			
		||||
            return driver;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    KPrintf("ChannelFindDriver cannot find the %s driver.return NULL\n", driver_name);
 | 
			
		||||
    return NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to find device pointer of certain ch by device name
 | 
			
		||||
* @param ch - ch pointer
 | 
			
		||||
* @param device_name - device name
 | 
			
		||||
* @return successful:EOK,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
ChDevType ChannelFindDevice(struct Channel *ch, const char *device_name)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(ch);
 | 
			
		||||
    struct ChDev *device = NONE;
 | 
			
		||||
 | 
			
		||||
    DoublelistType *node = NONE;
 | 
			
		||||
    DoublelistType *head = &ch->ch_devlink;
 | 
			
		||||
 | 
			
		||||
    for (node = head->node_next; node != head; node = node->node_next)
 | 
			
		||||
    {
 | 
			
		||||
        device = DOUBLE_LIST_ENTRY(node, struct ChDev, dev_link);
 | 
			
		||||
 | 
			
		||||
        if(!strcmp(device->dev_name, device_name)) {
 | 
			
		||||
            return device;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    KPrintf("ChannelFindDevice cannot find the %s device.return NULL\n", device_name);
 | 
			
		||||
    return NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to set dev receive function callback
 | 
			
		||||
* @param dev - dev pointer
 | 
			
		||||
* @param dev_recv_callback - callback function
 | 
			
		||||
* @return successful:EOK,failed:ERROR
 | 
			
		||||
*/
 | 
			
		||||
uint32 ChannelDevRecvCallback(struct ChDev *dev, int (*dev_recv_callback) (void *dev, x_size_t length))
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(dev );
 | 
			
		||||
 | 
			
		||||
    dev->dev_recv_callback = dev_recv_callback;
 | 
			
		||||
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to open dev
 | 
			
		||||
* @param dev - dev pointer
 | 
			
		||||
* @return successful:EOK,failed:ERROR
 | 
			
		||||
*/
 | 
			
		||||
uint32 ChannelDevOpen(struct ChDev *dev)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(dev);
 | 
			
		||||
 | 
			
		||||
    int ret = EOK;
 | 
			
		||||
 | 
			
		||||
    if (dev->dev_done->open) {
 | 
			
		||||
        ret = dev->dev_done->open(dev);
 | 
			
		||||
        if(ret) {
 | 
			
		||||
            KPrintf("ChannelDevOpen error ret %u\n", ret);
 | 
			
		||||
            return ERROR;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to close dev
 | 
			
		||||
* @param dev - dev pointer
 | 
			
		||||
* @return successful:EOK,failed:ERROR
 | 
			
		||||
*/
 | 
			
		||||
uint32 ChannelDevClose(struct ChDev *dev)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(dev);
 | 
			
		||||
 | 
			
		||||
    int ret = EOK;
 | 
			
		||||
 | 
			
		||||
    if (dev->dev_done->close) {
 | 
			
		||||
        ret = dev->dev_done->close(dev);
 | 
			
		||||
        if(ret) {
 | 
			
		||||
            KPrintf("ChannelDevClose error ret %u\n", ret);
 | 
			
		||||
            return ERROR;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to write data to dev
 | 
			
		||||
* @param dev - dev pointer
 | 
			
		||||
* @param write_param - ChWriteParam
 | 
			
		||||
* @return successful:EOK,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
uint32 ChannelDevWriteData(struct ChDev *dev, struct ChWriteParam *write_param)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(dev);
 | 
			
		||||
 | 
			
		||||
    if (dev->dev_done->write) {
 | 
			
		||||
        return dev->dev_done->write(dev, write_param);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to read data from dev
 | 
			
		||||
* @param dev - dev pointer
 | 
			
		||||
* @param read_param - ChReadParam
 | 
			
		||||
* @return successful:EOK,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
uint32 ChannelDevReadData(struct ChDev *dev, struct ChReadParam *read_param)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(dev);
 | 
			
		||||
 | 
			
		||||
    if (dev->dev_done->read) {
 | 
			
		||||
        return dev->dev_done->read(dev, read_param);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @Description: support to configure drv, include OPE_CFG and OPE_INT
 | 
			
		||||
* @param drv - drv pointer
 | 
			
		||||
* @param config - ChConfigInfo
 | 
			
		||||
* @return successful:EOK,failed:NONE
 | 
			
		||||
*/
 | 
			
		||||
uint32 ChannelDrvConfigure(struct ChDrv *drv, struct ChConfigInfo *config)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(drv);
 | 
			
		||||
    CHECK_CH_PARAM(config);
 | 
			
		||||
 | 
			
		||||
    int ret = EOK;
 | 
			
		||||
 | 
			
		||||
    if (drv->configure) {
 | 
			
		||||
        ret = drv->configure(drv, config);
 | 
			
		||||
        if(ret) {
 | 
			
		||||
            KPrintf("ChannelDrvCfg error, ret %u\n", ret);
 | 
			
		||||
            return ERROR;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PlcChannelInit(struct PlcChannel* plc_ch, const char* ch_name)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(plc_ch);
 | 
			
		||||
    CHECK_CH_PARAM(ch_name);
 | 
			
		||||
    int ret = EOK;
 | 
			
		||||
 | 
			
		||||
    if(CHANNEL_INSTALL != plc_ch->ch.ch_state)
 | 
			
		||||
    {
 | 
			
		||||
        strncpy(plc_ch->ch.ch_name, ch_name, NAME_NUM_MAX);
 | 
			
		||||
        plc_ch->ch.ch_type = CH_PLC_TYPE;
 | 
			
		||||
        plc_ch->ch.ch_state = CHANNEL_INSTALL;
 | 
			
		||||
        plc_ch->ch.private_data = plc_ch->private_data;
 | 
			
		||||
        ret = ChannelRegister(&plc_ch->ch);
 | 
			
		||||
 | 
			
		||||
        if(EOK != ret)
 | 
			
		||||
        {
 | 
			
		||||
            KPrintf("PlcChannelInit ChannelRegister error %u\n", ret);
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        KPrintf("PlcChannelInit ChannelRegister channel has been register state %u\n",
 | 
			
		||||
                plc_ch->ch.ch_state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PlcDriverInit(struct PlcDriver* plc_driver, const char* driver_name)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(plc_driver);
 | 
			
		||||
    CHECK_CH_PARAM(driver_name);
 | 
			
		||||
    int ret = EOK;
 | 
			
		||||
 | 
			
		||||
    if(CHDRV_INSTALL != plc_driver->driver.driver_state)
 | 
			
		||||
    {
 | 
			
		||||
        plc_driver->driver.driver_type = CHDRV_PLC_TYPE;
 | 
			
		||||
        plc_driver->driver.driver_state = CHDRV_INSTALL;
 | 
			
		||||
        strncpy(plc_driver->driver.drv_name, driver_name, NAME_NUM_MAX);
 | 
			
		||||
        plc_driver->driver.configure = plc_driver->configure;
 | 
			
		||||
        ret = PlcDriverRegister(&plc_driver->driver);
 | 
			
		||||
 | 
			
		||||
        if(EOK != ret)
 | 
			
		||||
        {
 | 
			
		||||
            KPrintf("PlcDriverInit DriverRegister error %u\n", ret);
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        KPrintf("PlcDriverInit Driver %s has been register state %u\n",
 | 
			
		||||
                driver_name, plc_driver->driver.driver_state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PlcReleaseChannel(struct PlcChannel* plc_ch)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(plc_ch);
 | 
			
		||||
    return ChannelRelease(&plc_ch->ch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PlcDriverAttachToChannel(const char* drv_name, const char* ch_name)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(drv_name);
 | 
			
		||||
    CHECK_CH_PARAM(ch_name);
 | 
			
		||||
    int ret = EOK;
 | 
			
		||||
    struct Channel* ch;
 | 
			
		||||
    struct ChDrv* driver;
 | 
			
		||||
    ch = ChannelFind(ch_name);
 | 
			
		||||
 | 
			
		||||
    if(NONE == ch)
 | 
			
		||||
    {
 | 
			
		||||
        KPrintf("PlcDriverAttachToChannel find plc channel error!name %s\n", ch_name);
 | 
			
		||||
        return ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(CH_PLC_TYPE == ch->ch_type)
 | 
			
		||||
    {
 | 
			
		||||
        driver = PlcDriverFind(drv_name, CHDRV_PLC_TYPE);
 | 
			
		||||
 | 
			
		||||
        if(NONE == driver)
 | 
			
		||||
        {
 | 
			
		||||
            KPrintf("PlcDriverAttachToChannel find plc driver error!name %s\n", drv_name);
 | 
			
		||||
            return ERROR;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(CHDRV_PLC_TYPE == driver->driver_type)
 | 
			
		||||
        {
 | 
			
		||||
            ret = DriverRegisterToChannel(ch, driver);
 | 
			
		||||
 | 
			
		||||
            if(EOK != ret)
 | 
			
		||||
            {
 | 
			
		||||
                KPrintf("PlcDriverAttachToChannel DriverRegisterToBus error %u\n", ret);
 | 
			
		||||
                return ERROR;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,278 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2022 AIIT XUOS Lab
 | 
			
		||||
* XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @file plc_channel.h
 | 
			
		||||
* @brief define ch driver framework function and common API
 | 
			
		||||
* @version 1.0
 | 
			
		||||
* @author AIIT XUOS Lab
 | 
			
		||||
* @date 2022-03-01
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef __PLC_CHANNEL_H_
 | 
			
		||||
#define __PLC_CHANNEL_H_
 | 
			
		||||
 | 
			
		||||
#include "list.h"
 | 
			
		||||
 | 
			
		||||
#define x_OffPos uint32
 | 
			
		||||
#define x_size_t size_t
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define OPE_INT                 0x0000
 | 
			
		||||
#define OPE_CFG                 0x0001
 | 
			
		||||
 | 
			
		||||
#define OPER_WDT_SET_TIMEOUT    0x0002
 | 
			
		||||
#define OPER_WDT_KEEPALIVE      0x0003
 | 
			
		||||
 | 
			
		||||
#define CHECK_CH_PARAM(param)            \
 | 
			
		||||
do                                     \
 | 
			
		||||
{                                      \
 | 
			
		||||
    if(param == NONE) {                \
 | 
			
		||||
        KPrintf("PARAM CHECK FAILED ...%s %d %s is NULL.\n",__FUNCTION__,__LINE__,#param); \
 | 
			
		||||
        while(RET_TRUE);               \
 | 
			
		||||
    }                                  \
 | 
			
		||||
}while (0)
 | 
			
		||||
 | 
			
		||||
typedef struct Channel *ChannelType;
 | 
			
		||||
typedef struct ChDev *ChDevType;
 | 
			
		||||
typedef struct ChDrv *ChDrvType;
 | 
			
		||||
 | 
			
		||||
/* need to add new ch type in ../tool/shell/letter-shell/cmd.c, ensure ShowBus cmd supported*/
 | 
			
		||||
enum ChType_e
 | 
			
		||||
{
 | 
			
		||||
    CH_PLC_TYPE,
 | 
			
		||||
    CH_END_TYPE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum ChState_e
 | 
			
		||||
{
 | 
			
		||||
    CHANNEL_INIT = 0,
 | 
			
		||||
    CHANNEL_INSTALL,
 | 
			
		||||
    CHANNEL_UNINSTALL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum ChDevType_e
 | 
			
		||||
{
 | 
			
		||||
    CHDEV_PLC_TYPE,
 | 
			
		||||
    CHDEV_END_TYPE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum ChDevState_e
 | 
			
		||||
{
 | 
			
		||||
    CHDEV_INIT = 0,
 | 
			
		||||
    CHDEV_INSTALL,
 | 
			
		||||
    CHDEV_UNINSTALL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum ChDrvType_e
 | 
			
		||||
{
 | 
			
		||||
    CHDRV_PLC_TYPE,
 | 
			
		||||
    CHDRV_END_TYPE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum ChDrvState_e
 | 
			
		||||
{
 | 
			
		||||
    CHDRV_INIT = 0,
 | 
			
		||||
    CHDRV_INSTALL,
 | 
			
		||||
    CHDRV_UNINSTALL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ChConfigInfo
 | 
			
		||||
{
 | 
			
		||||
    int configure_cmd;
 | 
			
		||||
    void *private_data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ChReadParam
 | 
			
		||||
{
 | 
			
		||||
    x_OffPos pos;
 | 
			
		||||
    void* buffer;
 | 
			
		||||
    x_size_t size;
 | 
			
		||||
    x_size_t read_length;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ChWriteParam
 | 
			
		||||
{
 | 
			
		||||
    x_OffPos pos;
 | 
			
		||||
    const void* buffer;
 | 
			
		||||
    x_size_t size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//struct ChHalDevBlockParam
 | 
			
		||||
//{
 | 
			
		||||
//    uint32 cmd;
 | 
			
		||||
////tst by wly
 | 
			
		||||
////    struct DeviceBlockArrange dev_block;
 | 
			
		||||
////    struct DeviceBlockAddr *dev_addr;
 | 
			
		||||
//};
 | 
			
		||||
 | 
			
		||||
struct ChHalDevDone
 | 
			
		||||
{
 | 
			
		||||
    uint32 (*open) (void *dev);
 | 
			
		||||
    uint32 (*close) (void *dev);
 | 
			
		||||
    uint32 (*write) (void *dev, struct ChWriteParam *write_param);
 | 
			
		||||
    uint32 (*read) (void *dev, struct ChReadParam *read_param);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ChDev
 | 
			
		||||
{
 | 
			
		||||
    int8 dev_name[NAME_NUM_MAX];
 | 
			
		||||
    enum ChDevType_e dev_type;
 | 
			
		||||
    enum ChDevState_e dev_state;
 | 
			
		||||
 | 
			
		||||
    const struct ChHalDevDone *dev_done;
 | 
			
		||||
 | 
			
		||||
    int (*dev_recv_callback) (void *dev, x_size_t length);
 | 
			
		||||
//    int (*dev_block_control) (struct ChDev *dev, struct ChHalDevBlockParam *block_param);
 | 
			
		||||
 | 
			
		||||
    struct Channel *owner_ch;
 | 
			
		||||
    void *private_data;
 | 
			
		||||
 | 
			
		||||
    int32 dev_sem;
 | 
			
		||||
 | 
			
		||||
    DoublelistType  dev_link;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ChDrv
 | 
			
		||||
{
 | 
			
		||||
    int8 drv_name[NAME_NUM_MAX];
 | 
			
		||||
    enum ChDrvType_e driver_type;
 | 
			
		||||
    enum ChDrvState_e driver_state;
 | 
			
		||||
 | 
			
		||||
    uint32 (*configure)(void *drv, struct ChConfigInfo *config);
 | 
			
		||||
 | 
			
		||||
    struct Channel *owner_ch;
 | 
			
		||||
    void *private_data;
 | 
			
		||||
 | 
			
		||||
    DoublelistType  driver_link;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Channel
 | 
			
		||||
{
 | 
			
		||||
    int8 ch_name[NAME_NUM_MAX];
 | 
			
		||||
    enum ChType_e ch_type;
 | 
			
		||||
    enum ChState_e ch_state;
 | 
			
		||||
 | 
			
		||||
    int32 (*match)(struct ChDrv *driver, struct ChDev *device);
 | 
			
		||||
 | 
			
		||||
    int ch_lock;
 | 
			
		||||
 | 
			
		||||
    struct ChDev *owner_haldev;
 | 
			
		||||
    struct ChDrv *owner_driver;
 | 
			
		||||
 | 
			
		||||
    void *private_data;
 | 
			
		||||
 | 
			
		||||
    /*manage the drv of the channel*/
 | 
			
		||||
    uint8 driver_cnt;
 | 
			
		||||
    uint8 ch_drvlink_flag;
 | 
			
		||||
    DoublelistType ch_drvlink;
 | 
			
		||||
 | 
			
		||||
    /*manage the dev of the channel*/
 | 
			
		||||
    uint8 haldev_cnt;
 | 
			
		||||
    uint8 ch_devlink_flag;
 | 
			
		||||
    DoublelistType ch_devlink;
 | 
			
		||||
 | 
			
		||||
    uint8 ch_cnt;
 | 
			
		||||
    uint8 ch_link_flag;
 | 
			
		||||
    DoublelistType  ch_link;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*Register the BUS,manage with the double linklist*/
 | 
			
		||||
int ChannelRegister(struct Channel *ch);
 | 
			
		||||
 | 
			
		||||
/*Release the BUS framework*/
 | 
			
		||||
int ChannelRelease(struct Channel *ch);
 | 
			
		||||
 | 
			
		||||
/*Unregister a certain kind of BUS*/
 | 
			
		||||
int ChannelUnregister(struct Channel *ch);
 | 
			
		||||
 | 
			
		||||
/*Register the driver to the channel*/
 | 
			
		||||
int DriverRegisterToChannel(struct Channel *ch, struct ChDrv *driver);
 | 
			
		||||
 | 
			
		||||
/*Register the device to the channel*/
 | 
			
		||||
int DeviceRegisterToChannel(struct Channel *ch, struct ChDev *device);
 | 
			
		||||
 | 
			
		||||
/*Delete the driver from the channel*/
 | 
			
		||||
int DriverDeleteFromChannel(struct Channel *ch, struct ChDrv *driver);
 | 
			
		||||
 | 
			
		||||
/*Delete the device from the channel*/
 | 
			
		||||
int DeviceDeleteFromChannel(struct Channel *ch, struct ChDev *device);
 | 
			
		||||
 | 
			
		||||
/*Find the ch with ch name*/
 | 
			
		||||
ChannelType ChannelFind(const char *ch_name);
 | 
			
		||||
 | 
			
		||||
/*Find the driver of cetain channel*/
 | 
			
		||||
ChDrvType ChannelFindDriver(struct Channel *ch, const char *driver_name);
 | 
			
		||||
 | 
			
		||||
/*Find the device of certain channel*/
 | 
			
		||||
ChDevType ChannelFindDevice(struct Channel *ch, const char *device_name);
 | 
			
		||||
 | 
			
		||||
/*Dev receive data callback function*/
 | 
			
		||||
uint32 ChannelDevRecvCallback(struct ChDev *dev, int (*dev_recv_callback) (void *dev, x_size_t length));
 | 
			
		||||
 | 
			
		||||
/*Open the device of the channel*/
 | 
			
		||||
uint32 ChannelDevOpen(struct ChDev *dev);
 | 
			
		||||
 | 
			
		||||
/*Close the device of the channel*/
 | 
			
		||||
uint32 ChannelDevClose(struct ChDev *dev);
 | 
			
		||||
 | 
			
		||||
/*Write data to the device*/
 | 
			
		||||
uint32 ChannelDevWriteData(struct ChDev *dev, struct ChWriteParam *write_param);
 | 
			
		||||
 | 
			
		||||
/*Read data from the device*/
 | 
			
		||||
uint32 ChannelDevReadData(struct ChDev *dev, struct ChReadParam *read_param);
 | 
			
		||||
 | 
			
		||||
/*Configure the driver of the channel*/
 | 
			
		||||
uint32 ChannelDrvConfigure(struct ChDrv *drv, struct ChConfigInfo *config);
 | 
			
		||||
 | 
			
		||||
/*Obtain the ch using a certain dev*/
 | 
			
		||||
int DeviceObtainChannel(struct Channel *ch, struct ChDev *dev, const char *drv_name, struct ChConfigInfo *config);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct PlcDriver
 | 
			
		||||
{
 | 
			
		||||
    struct ChDrv driver;
 | 
			
		||||
    uint32 (*configure) (void *drv, struct ChConfigInfo *cfg);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct PlcChannel
 | 
			
		||||
{
 | 
			
		||||
    struct Channel ch;
 | 
			
		||||
    void *private_data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*Register the plc bus*/
 | 
			
		||||
int PlcChannelInit(struct PlcChannel *plc_ch, const char *ch_name);
 | 
			
		||||
 | 
			
		||||
/*Register the plc driver*/
 | 
			
		||||
int PlcDriverInit(struct PlcDriver *plc_driver, const char *driver_name);
 | 
			
		||||
 | 
			
		||||
/*Release the plc device*/
 | 
			
		||||
int PlcReleaseChannel(struct PlcChannel *plc_ch);
 | 
			
		||||
 | 
			
		||||
/*Register the plc driver to the plc bus*/
 | 
			
		||||
int PlcDriverAttachToChannel(const char *drv_name, const char *ch_name);
 | 
			
		||||
 | 
			
		||||
/*Register the driver, manage with the double linklist*/
 | 
			
		||||
int PlcDriverRegister(struct ChDrv *driver);
 | 
			
		||||
 | 
			
		||||
/*Find the register driver*/
 | 
			
		||||
ChDrvType PlcDriverFind(const char *drv_name, enum ChDrvType_e drv_type);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,189 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2021 AIIT XUOS Lab
 | 
			
		||||
* XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file plc.c
 | 
			
		||||
 * @brief plc relative activities
 | 
			
		||||
 * @version 1.0
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.12.15
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "ua_api.h"
 | 
			
		||||
#include "plc_channel.h"
 | 
			
		||||
#include "plc_device.h"
 | 
			
		||||
 | 
			
		||||
DoublelistType plcdev_list;
 | 
			
		||||
 | 
			
		||||
/******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/*Create the plc device linklist*/
 | 
			
		||||
static void PlcDeviceLinkInit()
 | 
			
		||||
{
 | 
			
		||||
    AppInitDoubleList(&plcdev_list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int PlcDeviceOpen(void *dev)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(dev);
 | 
			
		||||
 | 
			
		||||
    struct PlcDevice *plc_dev = (struct PlcDevice *)dev;
 | 
			
		||||
 | 
			
		||||
    if(plc_dev->net == PLC_IND_ENET_OPCUA)
 | 
			
		||||
    {
 | 
			
		||||
        return ua_open(plc_dev->priv_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void PlcDeviceClose(void *dev)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(dev);
 | 
			
		||||
 | 
			
		||||
    struct PlcDevice *plc_dev = (struct PlcDevice *)dev;
 | 
			
		||||
 | 
			
		||||
    if(plc_dev->net == PLC_IND_ENET_OPCUA)
 | 
			
		||||
    {
 | 
			
		||||
        ua_close(plc_dev->priv_data);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int PlcDeviceWrite(void *dev, const void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(dev);
 | 
			
		||||
 | 
			
		||||
    int ret;
 | 
			
		||||
    struct PlcDevice *plc_dev = (struct PlcDevice *)dev;
 | 
			
		||||
 | 
			
		||||
    if(plc_dev->net == PLC_IND_ENET_OPCUA)
 | 
			
		||||
    {
 | 
			
		||||
        ret = ua_write(plc_dev->priv_data, buf, len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int PlcDeviceRead(void *dev, void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(dev);
 | 
			
		||||
    CHECK_CH_PARAM(buf);
 | 
			
		||||
 | 
			
		||||
    int ret;
 | 
			
		||||
    struct PlcDevice *plc_dev = (struct PlcDevice *)dev;
 | 
			
		||||
 | 
			
		||||
    if(plc_dev->net == PLC_IND_ENET_OPCUA)
 | 
			
		||||
    {
 | 
			
		||||
        ret = ua_read(plc_dev->priv_data, buf, len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct PlcOps plc_done =
 | 
			
		||||
{
 | 
			
		||||
    .open = PlcDeviceOpen,
 | 
			
		||||
    .close = PlcDeviceClose,
 | 
			
		||||
    .write = PlcDeviceWrite,
 | 
			
		||||
    .read = PlcDeviceRead,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* find PLC device with device name */
 | 
			
		||||
struct ChDev *PlcDevFind(const char *dev_name)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(dev_name);
 | 
			
		||||
 | 
			
		||||
    struct PlcDevice *device = NONE;
 | 
			
		||||
    struct ChDev *haldev = NONE;
 | 
			
		||||
 | 
			
		||||
    DoublelistType *node = NONE;
 | 
			
		||||
    DoublelistType *head = &plcdev_list;
 | 
			
		||||
 | 
			
		||||
    for (node = head->node_next; node != head; node = node->node_next) {
 | 
			
		||||
        device = DOUBLE_LIST_ENTRY(node, struct PlcDevice, link);
 | 
			
		||||
        if (!strcmp(device->name, dev_name)) {
 | 
			
		||||
            haldev = &device->haldev;
 | 
			
		||||
            return haldev;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    plc_print("plc: [%s] cannot find the %s device\n", __func__, dev_name);
 | 
			
		||||
    return NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PlcDevRegister(struct PlcDevice *plc_device, void *plc_param, const char *device_name)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(plc_device);
 | 
			
		||||
    CHECK_CH_PARAM(device_name);
 | 
			
		||||
 | 
			
		||||
    int ret = EOK;
 | 
			
		||||
    static uint8_t dev_link_flag = 0;
 | 
			
		||||
 | 
			
		||||
    if (!dev_link_flag) {
 | 
			
		||||
        PlcDeviceLinkInit();
 | 
			
		||||
        dev_link_flag = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (CHDEV_INSTALL != plc_device->state) {
 | 
			
		||||
        strncpy(plc_device->haldev.dev_name, device_name, NAME_NUM_MAX);
 | 
			
		||||
        plc_device->haldev.dev_type = CHDEV_PLC_TYPE;
 | 
			
		||||
        plc_device->haldev.dev_state = CHDEV_INSTALL;
 | 
			
		||||
 | 
			
		||||
        strncpy(plc_device->name, device_name, strlen(device_name));
 | 
			
		||||
        plc_device->ops = &plc_done;
 | 
			
		||||
 | 
			
		||||
        AppDoubleListInsertNodeAfter(&plcdev_list, &(plc_device->link));
 | 
			
		||||
        plc_device->state = CHDEV_INSTALL;
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        KPrintf("PlcDevRegister device %s has been register state%u\n", device_name, plc_device->state);
 | 
			
		||||
        ret = ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PlcDeviceAttachToChannel(const char *dev_name, const char *ch_name)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(dev_name);
 | 
			
		||||
    CHECK_CH_PARAM(ch_name);
 | 
			
		||||
 | 
			
		||||
    int ret = EOK;
 | 
			
		||||
 | 
			
		||||
    struct Channel *ch;
 | 
			
		||||
    struct ChDev *device;
 | 
			
		||||
 | 
			
		||||
    ch = ChannelFind(ch_name);
 | 
			
		||||
    if (NONE == ch) {
 | 
			
		||||
        KPrintf("PlcDeviceAttachToChannel find plc ch error!name %s\n", ch_name);
 | 
			
		||||
        return ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (CH_PLC_TYPE == ch->ch_type) {
 | 
			
		||||
        device = PlcDevFind(dev_name);
 | 
			
		||||
        if (NONE == device) {
 | 
			
		||||
            KPrintf("PlcDeviceAttachToChannel find plc device %s error!\n", dev_name);
 | 
			
		||||
            return ERROR;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (CHDEV_PLC_TYPE == device->dev_type) {
 | 
			
		||||
            ret = DeviceRegisterToChannel(ch, device);
 | 
			
		||||
            if (EOK != ret) {
 | 
			
		||||
                KPrintf("PlcDeviceAttachToChannel DeviceRegisterToChannel error %u\n", ret);
 | 
			
		||||
                return ERROR;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return EOK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -11,28 +11,38 @@
 | 
			
		|||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file plc.h
 | 
			
		||||
 * @file plc_dev.h
 | 
			
		||||
 * @brief plc relative definition and structure
 | 
			
		||||
 * @version 1.0
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.12.15
 | 
			
		||||
 * @date 2022-01-24
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "xs_klist.h"
 | 
			
		||||
#ifndef __PLC_DEV_H_
 | 
			
		||||
#define __PLC_DEV_H_
 | 
			
		||||
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "plc_channel.h"
 | 
			
		||||
 | 
			
		||||
#undef open
 | 
			
		||||
#undef close
 | 
			
		||||
#undef read
 | 
			
		||||
#undef write
 | 
			
		||||
 | 
			
		||||
#define IP_ADDR_SIZE 32
 | 
			
		||||
#define PLC_NAME_SIZE 32
 | 
			
		||||
 | 
			
		||||
// PLC device information
 | 
			
		||||
struct PlcInfo {
 | 
			
		||||
typedef struct PlcInfo {
 | 
			
		||||
    uint32_t ability;      // PLC ability
 | 
			
		||||
    uint32_t id;           // PLC Device ID
 | 
			
		||||
    uint32_t soft_version; // software version
 | 
			
		||||
    uint32_t hard_version; // hardware version
 | 
			
		||||
    uint32_t date;         // manufact date
 | 
			
		||||
    const char *vendor;    // vendor
 | 
			
		||||
    const char *model;     // product model
 | 
			
		||||
};
 | 
			
		||||
    const char *model;     // model
 | 
			
		||||
    const char *product;   // product
 | 
			
		||||
}PlcInfoType;
 | 
			
		||||
 | 
			
		||||
enum PlcSerialType {
 | 
			
		||||
    PLC_SERIAL_232,
 | 
			
		||||
| 
						 | 
				
			
			@ -55,13 +65,13 @@ union PlcCfg {
 | 
			
		|||
struct PlcDevice;
 | 
			
		||||
 | 
			
		||||
// operation API
 | 
			
		||||
struct PlcOps {
 | 
			
		||||
   int (*open)(struct PlcDevice *pdev); // open and connect PLC device
 | 
			
		||||
   void (*close)(struct PlcDevice*pdev); // close and disconnect PLC device
 | 
			
		||||
   int (*read)(struct PlcDevice* pdev, void *buf, size_t len); // read data from PLC
 | 
			
		||||
   int (*write)(struct PlcDevice* pdev, const void *buf, size_t len); // write data from PLC
 | 
			
		||||
   int (*ioctl)(struct PlcDevice* pdev, int cmd, void *arg); // send control command to PLC
 | 
			
		||||
};
 | 
			
		||||
typedef struct PlcOps {
 | 
			
		||||
   int (*open)(void *dev); // open and connect PLC device
 | 
			
		||||
   void (*close)(void* dev); // close and disconnect PLC device
 | 
			
		||||
   int (*read)(void* dev, void *buf, size_t len); // read data from PLC
 | 
			
		||||
   int (*write)(void* dev, const void *buf, size_t len); // write data from PLC
 | 
			
		||||
   int (*ioctl)(void* dev, int cmd, void *arg); // send control command to PLC
 | 
			
		||||
}PlcOpsType;
 | 
			
		||||
 | 
			
		||||
enum PlcCtlType {
 | 
			
		||||
    PLC_CTRL_TYPE_HSC,
 | 
			
		||||
| 
						 | 
				
			
			@ -69,15 +79,13 @@ enum PlcCtlType {
 | 
			
		|||
    PLC_CTRL_TYPE_PHASING
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define PLC_ABILITY_HSC     ((uint32_t)(1 << PLC_CTRL_TYPE_HSC))
 | 
			
		||||
#define PLC_ABILITY_PID     ((uint32_t)(1 << PLC_CTRL_TYPE_PID))
 | 
			
		||||
#define PLC_ABILITY_PHASING ((uint32_t)(1 << PLC_CTRL_TYPE_PHASING))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
enum PlcIndHybridNet
 | 
			
		||||
{
 | 
			
		||||
    //PLC Field Bus
 | 
			
		||||
    // PLC Field Bus
 | 
			
		||||
    PLC_IND_FIELD_MODBUS_485,
 | 
			
		||||
    PLC_IND_FIELD_PROFIBUS,
 | 
			
		||||
    PLC_IND_FIELD_CANOPEN,
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +99,7 @@ enum PlcIndHybridNet
 | 
			
		|||
    PLC_IND_ENET_SERCOS,
 | 
			
		||||
    PLC_IND_ENET_OPCUA,
 | 
			
		||||
 | 
			
		||||
    //PLC wireless net
 | 
			
		||||
    // PLC wireless net
 | 
			
		||||
    PLC_IND_WIRELESS
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -103,22 +111,43 @@ enum PlcTransType
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
//communication interface
 | 
			
		||||
struct PlcInterface
 | 
			
		||||
typedef struct PlcInterface
 | 
			
		||||
{
 | 
			
		||||
    enum PlcIndHybridNet net;
 | 
			
		||||
    enum PlcTransType trans;
 | 
			
		||||
    char ip_addr[IP_ADDR_SIZE];
 | 
			
		||||
    char attrib;
 | 
			
		||||
};
 | 
			
		||||
}PlcInterfaceType;
 | 
			
		||||
 | 
			
		||||
// identify PLC device
 | 
			
		||||
struct PlcDevice {
 | 
			
		||||
    const char name[PLC_NAME_SIZE]; /* name of the  device */
 | 
			
		||||
typedef struct PlcDevice {
 | 
			
		||||
    struct ChDev haldev; /* hardware device driver for channel */
 | 
			
		||||
    enum ChDevState_e state;
 | 
			
		||||
 | 
			
		||||
    char name[PLC_NAME_SIZE]; /* name of the device */
 | 
			
		||||
    enum PlcCtlType type; /* PLC Control Type */
 | 
			
		||||
    enum PlcIndHybridNet net;
 | 
			
		||||
    enum PlcTransType trans;
 | 
			
		||||
 | 
			
		||||
    struct PlcInfo info;/* Plc info, such as vendor name and model name */
 | 
			
		||||
    union PlcCfg cfg;
 | 
			
		||||
    struct PlcOps ops; /* filesystem-like APIs for data transferring */
 | 
			
		||||
    struct PlcOps *ops; /* filesystem-like APIs for data transferring */
 | 
			
		||||
    struct PlcInterface interface; /* protocols used for transferring data from program to plc */
 | 
			
		||||
    DoubleLinklistType link;/* link list node */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
    void *priv_data; /* private data for different PLC*/
 | 
			
		||||
    DoublelistType link;/* link list node */
 | 
			
		||||
}PlcDeviceType;
 | 
			
		||||
 | 
			
		||||
typedef struct PlcCtrlParam {
 | 
			
		||||
    void *node_id; // for node ID
 | 
			
		||||
    int value;
 | 
			
		||||
}PlcCtrlParamType;
 | 
			
		||||
 | 
			
		||||
#define plc_print KPrintf
 | 
			
		||||
 | 
			
		||||
/******************************************************************************/
 | 
			
		||||
 | 
			
		||||
int PlcDevRegister(struct PlcDevice *plc_device, void *plc_param, const char *device_name);
 | 
			
		||||
int PlcDeviceAttachToChannel(const char *dev_name, const char *ch_name);
 | 
			
		||||
 | 
			
		||||
/******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,71 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2020 AIIT XUOS Lab
 | 
			
		||||
* XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @file drv_plc.c
 | 
			
		||||
* @brief register plc drv function using bus driver framework
 | 
			
		||||
* @version 1.0
 | 
			
		||||
* @author AIIT XUOS Lab
 | 
			
		||||
* @date 2022-01-24
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "transform.h"
 | 
			
		||||
#include "plc_channel.h"
 | 
			
		||||
#include "plc_device.h"
 | 
			
		||||
 | 
			
		||||
static DoublelistType plcdrv_linklist;
 | 
			
		||||
 | 
			
		||||
/******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/*Create the driver linklist*/
 | 
			
		||||
static void PlcDrvLinkInit()
 | 
			
		||||
{
 | 
			
		||||
    AppInitDoubleList(&plcdrv_linklist);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ChDrvType PlcDriverFind(const char *drv_name, enum ChDrvType_e drv_type)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(drv_name);
 | 
			
		||||
 | 
			
		||||
    struct ChDrv *driver = NONE;
 | 
			
		||||
 | 
			
		||||
    DoublelistType *node = NONE;
 | 
			
		||||
    DoublelistType *head = &plcdrv_linklist;
 | 
			
		||||
 | 
			
		||||
    for (node = head->node_next; node != head; node = node->node_next) {
 | 
			
		||||
        driver = DOUBLE_LIST_ENTRY(node, struct ChDrv, driver_link);
 | 
			
		||||
        if ((!strcmp(driver->drv_name, drv_name)) && (drv_type == driver->driver_type)) {
 | 
			
		||||
            return driver;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    KPrintf("PlcDriverFind cannot find the %s driver.return NULL\n", drv_name);
 | 
			
		||||
    return NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PlcDriverRegister(struct ChDrv *driver)
 | 
			
		||||
{
 | 
			
		||||
    CHECK_CH_PARAM(driver);
 | 
			
		||||
 | 
			
		||||
    int ret = EOK;
 | 
			
		||||
    static uint8_t driver_link_flag = 0;
 | 
			
		||||
 | 
			
		||||
    if (!driver_link_flag) {
 | 
			
		||||
        PlcDrvLinkInit();
 | 
			
		||||
        driver_link_flag = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    AppDoubleListInsertNodeAfter(&plcdrv_linklist, &(driver->driver_link));
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,4 @@
 | 
			
		|||
SRC_DIR := 
 | 
			
		||||
SRC_FILES := control.c
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
{
 | 
			
		||||
"siemens plc":
 | 
			
		||||
{
 | 
			
		||||
    "device type": "PLC",
 | 
			
		||||
    "control type": "HSC",
 | 
			
		||||
	"info":
 | 
			
		||||
	{
 | 
			
		||||
	    "plc ability"  : 1,
 | 
			
		||||
	    "plc device id": 1,
 | 
			
		||||
	    "soft version" : 1,
 | 
			
		||||
	    "hardware version": 1,
 | 
			
		||||
	    "date": "2022-1-28",
 | 
			
		||||
	    "vendor": "siemens",
 | 
			
		||||
	    "model":"S300"
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	"serial config":
 | 
			
		||||
	{
 | 
			
		||||
	    "serial type":"485",
 | 
			
		||||
	    "station id" : "station1",
 | 
			
		||||
	    "serial port" : 1
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	"network config":
 | 
			
		||||
	{
 | 
			
		||||
	    "ip addr" : "192.168.250.5",
 | 
			
		||||
	    "ip port" : 4840
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	"interface":
 | 
			
		||||
	{
 | 
			
		||||
	    "inhybridnet":"OPCUA",
 | 
			
		||||
	    "transport":"TCP",
 | 
			
		||||
	    "ip address": "192.168.250.5",
 | 
			
		||||
	    "attribute" : "1"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,8 @@
 | 
			
		|||
 | 
			
		||||
#include "cJSON.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void control_init(void)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6,6 +10,12 @@ void control_init(void)
 | 
			
		|||
 | 
			
		||||
void control_read_file()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,8 +83,7 @@ ifeq ($(CONFIG_USING_TENSORFLOWLITEMICRO),y)
 | 
			
		|||
		-Isource/third_party/ruy
 | 
			
		||||
	DEFINES += -DTF_LITE_USE_GLOBAL_CMATH_FUNCTIONS \
 | 
			
		||||
		-DTF_LITE_USE_GLOBAL_MAX \
 | 
			
		||||
		-DTF_LITE_USE_GLOBAL_MIN \
 | 
			
		||||
		-DTF_LITE_STATIC_MEMORY
 | 
			
		||||
		-DTF_LITE_USE_GLOBAL_MIN
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,8 +23,8 @@ $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(SRCS)))
 | 
			
		|||
 | 
			
		||||
LIBRARY_OBJS := $(filter-out tensorflow/lite/micro/examples/%, $(OBJS))
 | 
			
		||||
 | 
			
		||||
CXXFLAGS += -std=c++11 -fno-rtti -fno-exceptions -fno-threadsafe-statics -fno-unwind-tables -ffunction-sections -fdata-sections -fmessage-length=0 -DTF_LITE_STATIC_MEMORY -DTF_LITE_DISABLE_X86_NEON -O3 -Werror -Wsign-compare -Wdouble-promotion -Wshadow -Wunused-variable -Wmissing-field-initializers -Wunused-function -Wswitch -Wvla -Wall -Wextra -Wstrict-aliasing -Wno-unused-parameter  -DCMSIS_NN -DTF_LITE_USE_CTIME -I. -I./third_party/gemmlowp -I./third_party/flatbuffers/include -I./third_party/ruy
 | 
			
		||||
CCFLAGS +=  -std=c11 -fno-unwind-tables -ffunction-sections -fdata-sections -fmessage-length=0 -DTF_LITE_STATIC_MEMORY -DTF_LITE_DISABLE_X86_NEON -O3 -Werror -Wsign-compare -Wdouble-promotion -Wshadow -Wunused-variable -Wmissing-field-initializers -Wunused-function -Wswitch -Wvla -Wall -Wextra -Wstrict-aliasing -Wno-unused-parameter  -DCMSIS_NN -DTF_LITE_USE_CTIME -I. -I./third_party/gemmlowp -I./third_party/flatbuffers/include -I./third_party/ruy
 | 
			
		||||
CXXFLAGS += -std=c++11 -fno-rtti -fno-exceptions -fno-threadsafe-statics -fno-unwind-tables -ffunction-sections -fdata-sections -fmessage-length=0 -DTF_LITE_DISABLE_X86_NEON -O3 -Werror -Wsign-compare -Wdouble-promotion -Wshadow -Wunused-variable -Wmissing-field-initializers -Wunused-function -Wswitch -Wvla -Wall -Wextra -Wstrict-aliasing -Wno-unused-parameter  -DCMSIS_NN -DTF_LITE_USE_CTIME -I. -I./third_party/gemmlowp -I./third_party/flatbuffers/include -I./third_party/ruy
 | 
			
		||||
CCFLAGS +=  -std=c11 -fno-unwind-tables -ffunction-sections -fdata-sections -fmessage-length=0 -DTF_LITE_DISABLE_X86_NEON -O3 -Werror -Wsign-compare -Wdouble-promotion -Wshadow -Wunused-variable -Wmissing-field-initializers -Wunused-function -Wswitch -Wvla -Wall -Wextra -Wstrict-aliasing -Wno-unused-parameter  -DCMSIS_NN -DTF_LITE_USE_CTIME -I. -I./third_party/gemmlowp -I./third_party/flatbuffers/include -I./third_party/ruy
 | 
			
		||||
 | 
			
		||||
LDFLAGS +=  -lm
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,4 +66,25 @@ if SUPPORT_SENSOR_FRAMEWORK
 | 
			
		|||
        if SENSOR_HUMIDITY
 | 
			
		||||
        source "$APP_DIR/Framework/sensor/humidity/Kconfig"
 | 
			
		||||
        endif
 | 
			
		||||
 | 
			
		||||
        menuconfig SENSOR_WINDSPEED
 | 
			
		||||
                bool "Using wind speed sensor device"
 | 
			
		||||
                default n
 | 
			
		||||
        if SENSOR_WINDSPEED
 | 
			
		||||
        source "$APP_DIR/Framework/sensor/windspeed/Kconfig"
 | 
			
		||||
        endif
 | 
			
		||||
 | 
			
		||||
        menuconfig SENSOR_WINDDIRECTION
 | 
			
		||||
                bool "Using wind direction sensor device"
 | 
			
		||||
                default n
 | 
			
		||||
        if SENSOR_WINDDIRECTION
 | 
			
		||||
        source "$APP_DIR/Framework/sensor/winddirection/Kconfig"
 | 
			
		||||
        endif
 | 
			
		||||
 | 
			
		||||
        menuconfig SENSOR_ALTITUDE
 | 
			
		||||
                bool "Using altitude sensor device"
 | 
			
		||||
                default n
 | 
			
		||||
        if SENSOR_ALTITUDE
 | 
			
		||||
        source "$APP_DIR/Framework/sensor/altitude/Kconfig"
 | 
			
		||||
        endif
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,5 +45,17 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
 | 
			
		|||
        SRC_DIR += humidity
 | 
			
		||||
    endif
 | 
			
		||||
 | 
			
		||||
    ifeq ($(CONFIG_SENSOR_WINDSPEED),y)
 | 
			
		||||
        SRC_DIR += windspeed
 | 
			
		||||
    endif
 | 
			
		||||
 | 
			
		||||
    ifeq ($(CONFIG_SENSOR_WINDDIRECTION),y)
 | 
			
		||||
        SRC_DIR += winddirection
 | 
			
		||||
    endif
 | 
			
		||||
 | 
			
		||||
    ifeq ($(CONFIG_SENSOR_ALTITUDE),y)
 | 
			
		||||
        SRC_DIR += altitude
 | 
			
		||||
    endif
 | 
			
		||||
 | 
			
		||||
    include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
 | 
			
		||||
config SENSOR_BMP180
 | 
			
		||||
        bool "Using BMP180"
 | 
			
		||||
        default n
 | 
			
		||||
 | 
			
		||||
        if SENSOR_BMP180
 | 
			
		||||
                config SENSOR_DEVICE_BMP180
 | 
			
		||||
                        string "BMP180 sensor name"
 | 
			
		||||
                        default "bmp180"
 | 
			
		||||
                
 | 
			
		||||
                config SENSOR_QUANTITY_BMP180_ALTITUDE
 | 
			
		||||
                        string "BMP180 quantity name"
 | 
			
		||||
                        default "altitude_1"
 | 
			
		||||
                
 | 
			
		||||
                if ADD_XIZI_FETURES
 | 
			
		||||
                        config SENSOR_DEVICE_BMP180_DEV
 | 
			
		||||
                                string "BMP180 device name"
 | 
			
		||||
                                default "/dev/i2c1_dev0"
 | 
			
		||||
                                
 | 
			
		||||
                        config SENSOR_DEVICE_BMP180_I2C_ADDR
 | 
			
		||||
                                hex "BMP180 device i2c address"
 | 
			
		||||
                                default 0x77
 | 
			
		||||
                endif
 | 
			
		||||
 | 
			
		||||
                if ADD_NUTTX_FETURES
 | 
			
		||||
 | 
			
		||||
                endif
 | 
			
		||||
 | 
			
		||||
                if ADD_RTTHREAD_FETURES
 | 
			
		||||
 | 
			
		||||
                endif
 | 
			
		||||
        endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
ifeq ($(CONFIG_SENSOR_BMP180),y)
 | 
			
		||||
	SRC_DIR += bmp180
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
import os
 | 
			
		||||
Import('RTT_ROOT')
 | 
			
		||||
from building import *
 | 
			
		||||
 | 
			
		||||
cwd = GetCurrentDir()
 | 
			
		||||
objs = []
 | 
			
		||||
list = os.listdir(cwd)
 | 
			
		||||
 | 
			
		||||
for d in list:
 | 
			
		||||
    path = os.path.join(cwd, d)
 | 
			
		||||
    if os.path.isfile(os.path.join(path, 'SConscript')):
 | 
			
		||||
        objs = objs + SConscript(os.path.join(path, 'SConscript'))
 | 
			
		||||
 | 
			
		||||
Return('objs')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
SRC_FILES := bmp180.c
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
from building import *
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
cwd = GetCurrentDir()
 | 
			
		||||
src = []
 | 
			
		||||
if GetDepend(['SENSOR_BMP180']):
 | 
			
		||||
    src += ['bmp180.c']
 | 
			
		||||
group = DefineGroup('sensor altitude bmp180', src, depend = [], CPPPATH = [cwd])
 | 
			
		||||
 | 
			
		||||
Return('group')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,322 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2020 AIIT XUOS Lab
 | 
			
		||||
* XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file bmp180.c
 | 
			
		||||
 * @brief BMP180 altitude driver base sensor
 | 
			
		||||
 * @version 1.1
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.12.20
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sensor.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
static struct SensorDevice bmp180;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    int8_t ac_data[3];
 | 
			
		||||
    uint8_t unsigned_ac_data[3];
 | 
			
		||||
    int8_t b_data[2];
 | 
			
		||||
    int8_t m_data[3];
 | 
			
		||||
}Bmp180RegData;
 | 
			
		||||
 | 
			
		||||
static Bmp180RegData bmp180_reg_data;
 | 
			
		||||
 | 
			
		||||
const static unsigned char OSS = 0;  // Oversampling Setting
 | 
			
		||||
static long CalTemp_data = 0;
 | 
			
		||||
 | 
			
		||||
static struct SensorProductInfo info =
 | 
			
		||||
{
 | 
			
		||||
    (SENSOR_ABILITY_ALTITUDE),
 | 
			
		||||
    "BOSCH",
 | 
			
		||||
    "BMP180",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Open BMP180 sensor device
 | 
			
		||||
 * @param sdev - sensor device pointer
 | 
			
		||||
 * @return success : 0 error : -1
 | 
			
		||||
 */
 | 
			
		||||
static int SensorDeviceOpen(struct SensorDevice *sdev)
 | 
			
		||||
{
 | 
			
		||||
    int result;
 | 
			
		||||
    uint16_t i2c_dev_addr = SENSOR_DEVICE_BMP180_I2C_ADDR;
 | 
			
		||||
    
 | 
			
		||||
    sdev->fd = PrivOpen(SENSOR_DEVICE_BMP180_DEV, O_RDWR);
 | 
			
		||||
    if (sdev->fd < 0) {
 | 
			
		||||
        printf("open %s error\n", SENSOR_DEVICE_BMP180_DEV);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct PrivIoctlCfg ioctl_cfg;
 | 
			
		||||
    ioctl_cfg.ioctl_driver_type = I2C_TYPE;
 | 
			
		||||
    ioctl_cfg.args = &i2c_dev_addr;
 | 
			
		||||
    result = PrivIoctl(sdev->fd, OPE_INT, &ioctl_cfg);
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Write sensor device
 | 
			
		||||
 * @param sdev - sensor device pointer
 | 
			
		||||
 * @param len - the length of the read data
 | 
			
		||||
 * @return success: 0 , failure: -1
 | 
			
		||||
 */
 | 
			
		||||
static int SensorDeviceWrite(struct SensorDevice *sdev, const void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    if (PrivWrite(sdev->fd, buf, len) < 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Read sensor device
 | 
			
		||||
 * @param sdev - sensor device pointer
 | 
			
		||||
 * @param len - the length of the read data
 | 
			
		||||
 * @return success: 0 , failure: -1
 | 
			
		||||
 */
 | 
			
		||||
static int SensorDeviceRead(struct SensorDevice *sdev, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    //Read i2c device data from i2c device address
 | 
			
		||||
    if (PrivRead(sdev->fd, sdev->buffer, len) < 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct SensorDone done =
 | 
			
		||||
{
 | 
			
		||||
    SensorDeviceOpen,
 | 
			
		||||
    NULL,
 | 
			
		||||
    SensorDeviceRead,
 | 
			
		||||
    SensorDeviceWrite,
 | 
			
		||||
    NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Init BMP180 sensor and register
 | 
			
		||||
 * @return void
 | 
			
		||||
 */
 | 
			
		||||
static void SensorDeviceBmp180Init(void)
 | 
			
		||||
{
 | 
			
		||||
    bmp180.name = SENSOR_DEVICE_BMP180;
 | 
			
		||||
    bmp180.info = &info;
 | 
			
		||||
    bmp180.done = &done;
 | 
			
		||||
    bmp180.status = SENSOR_DEVICE_PASSIVE;
 | 
			
		||||
 | 
			
		||||
    SensorDeviceRegister(&bmp180);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct SensorQuantity bmp180_altitude;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Stores all of the bmp180's calibration values into global variables
 | 
			
		||||
 * @return uint16_t reg data
 | 
			
		||||
 */
 | 
			
		||||
static uint16_t SensorDeviceBmp180ReadRegs(struct SensorDevice *sdev, char reg_addr)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t reg_data[2] = {0};
 | 
			
		||||
    
 | 
			
		||||
    if (SensorDeviceWrite(sdev, ®_addr, 1) < 0) {
 | 
			
		||||
        printf("SensorDeviceBmp180ReadRegs write reg 0x%x error. return 0x0\n", reg_addr);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (SensorDeviceRead(sdev, 2) < 0) {
 | 
			
		||||
        printf("SensorDeviceBmp180ReadRegs error. return 0x0\n");
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    reg_data[0] = sdev->buffer[0];
 | 
			
		||||
    reg_data[1] = sdev->buffer[1];
 | 
			
		||||
 | 
			
		||||
    return (uint16_t)(reg_data[0] << 8 | reg_data[1]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Read the uncompensated temperature value(ut)
 | 
			
		||||
 * @return uint16_t 0xF6 reg data
 | 
			
		||||
 */
 | 
			
		||||
static uint16_t SensorDeviceBmp180ReadUT(struct SensorDevice *sdev)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t data[2];
 | 
			
		||||
    data[0] = 0xF4;
 | 
			
		||||
    data[1] = 0x2E;
 | 
			
		||||
 | 
			
		||||
    if (SensorDeviceWrite(sdev, data, 2) < 0) {
 | 
			
		||||
        printf("SensorDeviceBmp180ReadUT write reg 0xF4 error. return 0x0\n");
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return SensorDeviceBmp180ReadRegs(sdev, 0xF6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Read the uncompensated pressure value(up)
 | 
			
		||||
 * @return uint16_t 0xF6 reg data
 | 
			
		||||
 */
 | 
			
		||||
static uint16_t SensorDeviceBmp180ReadUP(struct SensorDevice *sdev)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t data[2];
 | 
			
		||||
    data[0] = 0xF4;
 | 
			
		||||
    data[1] = 0x34 + (OSS << 6);
 | 
			
		||||
 | 
			
		||||
    if (SensorDeviceWrite(sdev, data, 2) < 0) {
 | 
			
		||||
        printf("SensorDeviceBmp180ReadUP write reg 0xF4 error. return 0x0\n");
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return SensorDeviceBmp180ReadRegs(sdev, 0xF6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Calculate temperature
 | 
			
		||||
 * @return uint16_t reg data
 | 
			
		||||
 */
 | 
			
		||||
static float SensorDeviceBmp180CalTemp(struct SensorDevice *sdev, uint16_t ut, Bmp180RegData *bmp180_reg_data)
 | 
			
		||||
{
 | 
			
		||||
    long x1, x2;
 | 
			
		||||
    x1 = (((long)ut - (long)bmp180_reg_data->unsigned_ac_data[2]) * (long)bmp180_reg_data->unsigned_ac_data[1]) >> 15;
 | 
			
		||||
    x2 = ((long)bmp180_reg_data->m_data[1] << 11) / (x1 + bmp180_reg_data->m_data[2]);
 | 
			
		||||
    CalTemp_data = x1 + x2;
 | 
			
		||||
    float temp = ((CalTemp_data + 8) >> 4);
 | 
			
		||||
    temp = temp / 10;
 | 
			
		||||
    return temp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Calculate pressure
 | 
			
		||||
 * @return float pressure
 | 
			
		||||
 */
 | 
			
		||||
static float SensorDeviceBmp180CalPressure(struct SensorDevice *sdev, uint16_t up, Bmp180RegData *bmp180_reg_data)
 | 
			
		||||
{
 | 
			
		||||
    long x1, x2, x3, y1, y2, pressure;
 | 
			
		||||
    unsigned long z1, z2;
 | 
			
		||||
 | 
			
		||||
    y2 = CalTemp_data - 4000;
 | 
			
		||||
    // Calculate y1 data
 | 
			
		||||
    x1 = (bmp180_reg_data->b_data[1] * (y2 * y2) >> 12) >> 11;
 | 
			
		||||
    x2 = (bmp180_reg_data->ac_data[1] * y2)>>11;
 | 
			
		||||
    x3 = x1 + x2;
 | 
			
		||||
    y1 = (((((long)bmp180_reg_data->ac_data[0]) * 4 + x3) << OSS) + 2) >> 2;
 | 
			
		||||
 | 
			
		||||
    // Calculate B4
 | 
			
		||||
    x1 = (bmp180_reg_data->ac_data[2] * y2) >> 13;
 | 
			
		||||
    x2 = (bmp180_reg_data->b_data[0] * ((y2 * y2) >> 12)) >> 16;
 | 
			
		||||
    x3 = ((x1 + x2) + 2) >> 2;
 | 
			
		||||
    z1 = (bmp180_reg_data->unsigned_ac_data[0] * (unsigned long)(x3 + 32768)) >> 15;
 | 
			
		||||
 | 
			
		||||
    z2 = ((unsigned long)(up - y1) * (50000 >> OSS));
 | 
			
		||||
    if (z2 < 0x80000000)
 | 
			
		||||
        pressure = (z2 << 1) / z1;
 | 
			
		||||
    else
 | 
			
		||||
        pressure = (z2 / z1) << 1;
 | 
			
		||||
 | 
			
		||||
    x1 = (pressure >> 8) * (pressure >> 8);
 | 
			
		||||
    x1 = (x1 * 3038) >> 16;
 | 
			
		||||
    x2 = (-7357 * pressure) >> 16;
 | 
			
		||||
    pressure += (x1 + x2 + 3791) >> 4;
 | 
			
		||||
 | 
			
		||||
    return pressure;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Calculate altitude
 | 
			
		||||
 * @return float Altitude
 | 
			
		||||
 */
 | 
			
		||||
static float SensorDeviceBmp180CalAltitude(float pressure)
 | 
			
		||||
{
 | 
			
		||||
    float A = pressure / 101325;
 | 
			
		||||
    float B = 1 / 5.25588;
 | 
			
		||||
    float altitude = pow(A, B);
 | 
			
		||||
    altitude = 1 - altitude;
 | 
			
		||||
    altitude = altitude / 0.0000225577;
 | 
			
		||||
 | 
			
		||||
    return altitude;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Analysis BMP180 temperature result
 | 
			
		||||
 * @param quant - sensor quantity pointer
 | 
			
		||||
 * @return quantity value
 | 
			
		||||
 */
 | 
			
		||||
static int32_t ReadAltitude(struct SensorQuantity *quant)
 | 
			
		||||
{
 | 
			
		||||
    if (!quant)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    memset(&bmp180_reg_data, 0 , sizeof(Bmp180RegData));
 | 
			
		||||
 | 
			
		||||
    uint16_t ut, up = 0;
 | 
			
		||||
    float bmp180_temperature, bmp180_pressure, bmp180_aititude;
 | 
			
		||||
    if (quant->sdev->done->read != NULL) {
 | 
			
		||||
        if (quant->sdev->status == SENSOR_DEVICE_PASSIVE) {
 | 
			
		||||
 | 
			
		||||
            bmp180_reg_data.ac_data[0] = SensorDeviceBmp180ReadRegs(quant->sdev, 0xAA);
 | 
			
		||||
            bmp180_reg_data.ac_data[1] = SensorDeviceBmp180ReadRegs(quant->sdev, 0xAC);
 | 
			
		||||
            bmp180_reg_data.ac_data[2] = SensorDeviceBmp180ReadRegs(quant->sdev, 0xAE);
 | 
			
		||||
            bmp180_reg_data.unsigned_ac_data[0] = SensorDeviceBmp180ReadRegs(quant->sdev, 0xB0);
 | 
			
		||||
            bmp180_reg_data.unsigned_ac_data[1] = SensorDeviceBmp180ReadRegs(quant->sdev, 0xB2);
 | 
			
		||||
            bmp180_reg_data.unsigned_ac_data[2] = SensorDeviceBmp180ReadRegs(quant->sdev, 0xB4);
 | 
			
		||||
            bmp180_reg_data.b_data[0] = SensorDeviceBmp180ReadRegs(quant->sdev, 0xB6);
 | 
			
		||||
            bmp180_reg_data.b_data[1] = SensorDeviceBmp180ReadRegs(quant->sdev, 0xB8);
 | 
			
		||||
            bmp180_reg_data.m_data[0] = SensorDeviceBmp180ReadRegs(quant->sdev, 0xBA);
 | 
			
		||||
            bmp180_reg_data.m_data[1] = SensorDeviceBmp180ReadRegs(quant->sdev, 0xBC);
 | 
			
		||||
            bmp180_reg_data.m_data[2] = SensorDeviceBmp180ReadRegs(quant->sdev, 0xBE);
 | 
			
		||||
 | 
			
		||||
            ut = SensorDeviceBmp180ReadUT(quant->sdev);
 | 
			
		||||
            up = SensorDeviceBmp180ReadUP(quant->sdev);
 | 
			
		||||
 | 
			
		||||
            bmp180_temperature = SensorDeviceBmp180CalTemp(quant->sdev, ut, &bmp180_reg_data);
 | 
			
		||||
            bmp180_pressure = SensorDeviceBmp180CalPressure(quant->sdev, up, &bmp180_reg_data);
 | 
			
		||||
            bmp180_aititude = SensorDeviceBmp180CalAltitude(bmp180_pressure);
 | 
			
		||||
 | 
			
		||||
            return (int32_t)bmp180_pressure;
 | 
			
		||||
        }
 | 
			
		||||
        if (quant->sdev->status == SENSOR_DEVICE_ACTIVE) {
 | 
			
		||||
            printf("Please set passive mode.\n");
 | 
			
		||||
        }
 | 
			
		||||
    }else{
 | 
			
		||||
        printf("%s don't have read done.\n", quant->name);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Init BMP180 temperature quantity and register
 | 
			
		||||
 * @return 0
 | 
			
		||||
 */
 | 
			
		||||
int Bmp180AltitudeInit(void)
 | 
			
		||||
{
 | 
			
		||||
    SensorDeviceBmp180Init();
 | 
			
		||||
    
 | 
			
		||||
    bmp180_altitude.name = SENSOR_QUANTITY_BMP180_ALTITUDE;
 | 
			
		||||
    bmp180_altitude.type = SENSOR_QUANTITY_ALTITUDE;
 | 
			
		||||
    bmp180_altitude.value.decimal_places = 1;
 | 
			
		||||
    bmp180_altitude.value.max_std = 1000;
 | 
			
		||||
    bmp180_altitude.value.min_std = 0;
 | 
			
		||||
    bmp180_altitude.value.last_value = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
    bmp180_altitude.value.max_value = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
    bmp180_altitude.value.min_value = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
    bmp180_altitude.sdev = &bmp180;
 | 
			
		||||
    bmp180_altitude.ReadValue = ReadAltitude;
 | 
			
		||||
 | 
			
		||||
    SensorQuantityRegister(&bmp180_altitude);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -46,3 +46,46 @@ config SENSOR_ZG09
 | 
			
		|||
 | 
			
		||||
                endif                
 | 
			
		||||
        endif
 | 
			
		||||
 | 
			
		||||
config SENSOR_G8S
 | 
			
		||||
        bool "Using g8-s"
 | 
			
		||||
        default n
 | 
			
		||||
 | 
			
		||||
        if SENSOR_G8S
 | 
			
		||||
                config SENSOR_DEVICE_G8S
 | 
			
		||||
                        string "g8-s sensor name"
 | 
			
		||||
                        default "g8-s"
 | 
			
		||||
                
 | 
			
		||||
                config SENSOR_QUANTITY_G8S_CO2
 | 
			
		||||
                        string "g8-s quantity name"
 | 
			
		||||
                        default "co2_2"
 | 
			
		||||
                
 | 
			
		||||
                if ADD_XIZI_FETURES
 | 
			
		||||
                        config SENSOR_G8S_DRIVER_EXTUART
 | 
			
		||||
                                bool "Using extra uart to support g8-s"
 | 
			
		||||
                                default n
 | 
			
		||||
 | 
			
		||||
                        config SENSOR_DEVICE_G8S_DEV
 | 
			
		||||
                                string "g8-s device uart path"
 | 
			
		||||
                                default "/dev/uart2_dev2"
 | 
			
		||||
                                depends on !SENSOR_G8S_DRIVER_EXTUART
 | 
			
		||||
 | 
			
		||||
                        if SENSOR_G8S_DRIVER_EXTUART
 | 
			
		||||
                                config SENSOR_DEVICE_G8S_DEV
 | 
			
		||||
                                        string "g8-s device extra uart path"
 | 
			
		||||
                                        default "/dev/extuart_dev4"
 | 
			
		||||
 | 
			
		||||
                                config SENSOR_DEVICE_G8S_DEV_EXT_PORT
 | 
			
		||||
                                        int "if g8-s device using extuart, choose port"
 | 
			
		||||
                                        default "4"
 | 
			
		||||
                        endif
 | 
			
		||||
                endif
 | 
			
		||||
 | 
			
		||||
                if ADD_NUTTX_FETURES
 | 
			
		||||
 | 
			
		||||
                endif
 | 
			
		||||
 | 
			
		||||
                if ADD_RTTHREAD_FETURES
 | 
			
		||||
 | 
			
		||||
                endif                
 | 
			
		||||
        endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,4 +2,8 @@ ifeq ($(CONFIG_SENSOR_ZG09),y)
 | 
			
		|||
	SRC_DIR += zg09
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(CONFIG_SENSOR_G8S),y)
 | 
			
		||||
	SRC_DIR += g8s
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
import os
 | 
			
		||||
Import('RTT_ROOT')
 | 
			
		||||
from building import *
 | 
			
		||||
 | 
			
		||||
cwd = GetCurrentDir()
 | 
			
		||||
objs = []
 | 
			
		||||
list = os.listdir(cwd)
 | 
			
		||||
 | 
			
		||||
for d in list:
 | 
			
		||||
    path = os.path.join(cwd, d)
 | 
			
		||||
    if os.path.isfile(os.path.join(path, 'SConscript')):
 | 
			
		||||
        objs = objs + SConscript(os.path.join(path, 'SConscript'))
 | 
			
		||||
 | 
			
		||||
Return('objs')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
SRC_FILES := g8s.c
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
from building import *
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
cwd = GetCurrentDir()
 | 
			
		||||
src = []
 | 
			
		||||
if GetDepend(['SENSOR_G8S']):
 | 
			
		||||
    src += ['g8s.c']
 | 
			
		||||
group = DefineGroup('sensor co2 g8s', src, depend = [], CPPPATH = [cwd])
 | 
			
		||||
 | 
			
		||||
Return('group')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,187 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2020 AIIT XUOS Lab
 | 
			
		||||
* XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file g8s.c
 | 
			
		||||
 * @brief G8S CO2 driver base sensor
 | 
			
		||||
 * @version 1.1
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.12.23
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sensor.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
static uint8_t g8s_read_instruction[8] = {0x52, 0x36, 0x09, 0x37, 0x38, 0x0D, 0x0A};
 | 
			
		||||
 | 
			
		||||
static struct SensorDevice g8s;
 | 
			
		||||
 | 
			
		||||
static struct SensorProductInfo info =
 | 
			
		||||
{
 | 
			
		||||
    SENSOR_ABILITY_CO2,
 | 
			
		||||
    "senTec",
 | 
			
		||||
    "G8S",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Open G8S sensor device
 | 
			
		||||
 * @param sdev - sensor device pointer
 | 
			
		||||
 * @return success: 1 , failure: other
 | 
			
		||||
 */
 | 
			
		||||
static int SensorDeviceOpen(struct SensorDevice *sdev)
 | 
			
		||||
{
 | 
			
		||||
    int result = 0;
 | 
			
		||||
 | 
			
		||||
    sdev->fd = PrivOpen(SENSOR_DEVICE_G8S_DEV, O_RDWR);
 | 
			
		||||
    if (sdev->fd < 0) {
 | 
			
		||||
        printf("open %s error\n", SENSOR_DEVICE_G8S_DEV);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    struct SerialDataCfg cfg;
 | 
			
		||||
    cfg.serial_baud_rate    = BAUD_RATE_9600;
 | 
			
		||||
    cfg.serial_data_bits    = DATA_BITS_8;
 | 
			
		||||
    cfg.serial_stop_bits    = STOP_BITS_1;
 | 
			
		||||
    cfg.serial_buffer_size  = 128;
 | 
			
		||||
    cfg.serial_parity_mode  = PARITY_NONE;
 | 
			
		||||
    cfg.serial_bit_order    = 0;
 | 
			
		||||
    cfg.serial_invert_mode  = 0;
 | 
			
		||||
#ifdef SENSOR_G8S_DRIVER_EXTUART
 | 
			
		||||
    cfg.ext_uart_no         = SENSOR_DEVICE_G8S_DEV_EXT_PORT;
 | 
			
		||||
    cfg.port_configure      = PORT_CFG_INIT;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    struct PrivIoctlCfg ioctl_cfg;
 | 
			
		||||
    ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
 | 
			
		||||
    ioctl_cfg.args = &cfg;
 | 
			
		||||
    result = PrivIoctl(sdev->fd, OPE_INT, &ioctl_cfg);
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Read sensor device
 | 
			
		||||
 * @param sdev - sensor device pointer
 | 
			
		||||
 * @param len - the length of the read data
 | 
			
		||||
 * @return get data length
 | 
			
		||||
 */
 | 
			
		||||
static int SensorDeviceRead(struct SensorDevice *sdev, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t tmp = 0;
 | 
			
		||||
 | 
			
		||||
    PrivWrite(sdev->fd, g8s_read_instruction, sizeof(g8s_read_instruction));
 | 
			
		||||
 | 
			
		||||
    if (PrivRead(sdev->fd, sdev->buffer, len) < 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct SensorDone done =
 | 
			
		||||
{
 | 
			
		||||
    SensorDeviceOpen,
 | 
			
		||||
    NULL,
 | 
			
		||||
    SensorDeviceRead,
 | 
			
		||||
    NULL,
 | 
			
		||||
    NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Init G8S sensor and register
 | 
			
		||||
 * @return void
 | 
			
		||||
 */
 | 
			
		||||
static void SensorDeviceG8sInit(void)
 | 
			
		||||
{
 | 
			
		||||
    g8s.name = SENSOR_DEVICE_G8S;
 | 
			
		||||
    g8s.info = &info;
 | 
			
		||||
    g8s.done = &done;
 | 
			
		||||
    g8s.status = SENSOR_DEVICE_PASSIVE;
 | 
			
		||||
 | 
			
		||||
    SensorDeviceRegister(&g8s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct SensorQuantity g8s_co2;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Analysis G8S CO2 result
 | 
			
		||||
 * @param quant - sensor quantity pointer
 | 
			
		||||
 * @return quantity value
 | 
			
		||||
 */
 | 
			
		||||
static int32_t QuantityRead(struct SensorQuantity *quant)
 | 
			
		||||
{
 | 
			
		||||
    if (!quant)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    int i, ascii_length;
 | 
			
		||||
    int32_t result = 0;
 | 
			
		||||
    uint8_t result_ascii[9], result_hex[9];
 | 
			
		||||
 | 
			
		||||
    memset(result_ascii, 0, 9);
 | 
			
		||||
    memset(result_hex, 0, 9);
 | 
			
		||||
 | 
			
		||||
    if (quant->sdev->done->read != NULL) {
 | 
			
		||||
        if(quant->sdev->status == SENSOR_DEVICE_PASSIVE) {
 | 
			
		||||
            quant->sdev->done->read(quant->sdev, 9);
 | 
			
		||||
 | 
			
		||||
            for (i = 0; i < 9; i ++) {
 | 
			
		||||
                if (0x09 == quant->sdev->buffer[i]) {
 | 
			
		||||
                    ascii_length = i;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                result_ascii[i] = quant->sdev->buffer[i];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (8 == ascii_length) {
 | 
			
		||||
                for (i = 0; i < ascii_length; i ++) {
 | 
			
		||||
                    result_hex[i] = result_ascii[i] - 0x30;
 | 
			
		||||
                    result += result_hex[i] * pow(10, ascii_length - 1 - i);
 | 
			
		||||
                }
 | 
			
		||||
                return result;
 | 
			
		||||
            } else {
 | 
			
		||||
                printf("This reading is wrong\n");
 | 
			
		||||
                result = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
                return result;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (quant->sdev->status == SENSOR_DEVICE_ACTIVE) {
 | 
			
		||||
            printf("Please set passive mode.\n");
 | 
			
		||||
        }
 | 
			
		||||
    }else{
 | 
			
		||||
        printf("%s don't have read done.\n", quant->name);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Init G8S CO2 quantity and register
 | 
			
		||||
 * @return 0
 | 
			
		||||
 */
 | 
			
		||||
int G8sCo2Init(void)
 | 
			
		||||
{
 | 
			
		||||
    SensorDeviceG8sInit();
 | 
			
		||||
    
 | 
			
		||||
    g8s_co2.name = SENSOR_QUANTITY_G8S_CO2;
 | 
			
		||||
    g8s_co2.type = SENSOR_QUANTITY_CO2;
 | 
			
		||||
    g8s_co2.value.decimal_places = 0;
 | 
			
		||||
    g8s_co2.value.max_std = 2000;
 | 
			
		||||
    g8s_co2.value.min_std = 0;
 | 
			
		||||
    g8s_co2.value.last_value = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
    g8s_co2.value.max_value = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
    g8s_co2.value.min_value = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
    g8s_co2.sdev = &g8s;
 | 
			
		||||
    g8s_co2.ReadValue = QuantityRead;
 | 
			
		||||
 | 
			
		||||
    SensorQuantityRegister(&g8s_co2);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -69,28 +69,11 @@ static int SensorDeviceOpen(struct SensorDevice *sdev)
 | 
			
		|||
 */
 | 
			
		||||
static int SensorDeviceRead(struct SensorDevice *sdev, size_t len)
 | 
			
		||||
{
 | 
			
		||||
#ifdef ADD_NUTTX_FETURES
 | 
			
		||||
    int ret;
 | 
			
		||||
    ret = PrivRead(sdev->fd, sdev->buffer, len);
 | 
			
		||||
    if (ret != len ){
 | 
			
		||||
        perror("Failed to read data!\n");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
#else
 | 
			
		||||
    //send i2c device start signal and address, need to implemente in OS i2c driver
 | 
			
		||||
    if (PrivWrite(sdev->fd, NULL, 0) != 1)
 | 
			
		||||
        return -1;
 | 
			
		||||
    
 | 
			
		||||
    PrivTaskDelay(50);
 | 
			
		||||
 | 
			
		||||
    //Read i2c device data from i2c device address
 | 
			
		||||
    if (PrivRead(sdev->fd, sdev->buffer, len) != 1)
 | 
			
		||||
    if (PrivRead(sdev->fd, sdev->buffer, len) < 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct SensorDone done =
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,6 +55,9 @@ extern "C" {
 | 
			
		|||
#define SENSOR_ABILITY_IAQ      ((uint32_t)(1 << SENSOR_QUANTITY_IAQ))
 | 
			
		||||
#define SENSOR_ABILITY_TVOC     ((uint32_t)(1 << SENSOR_QUANTITY_TVOC))
 | 
			
		||||
#define SENSOR_ABILITY_HCHO     ((uint32_t)(1 << SENSOR_QUANTITY_HCHO))
 | 
			
		||||
#define SENSOR_ABILITY_WINDSPEED        ((uint32_t)(1 << SENSOR_QUANTITY_WINDSPEED))
 | 
			
		||||
#define SENSOR_ABILITY_WINDDIRECTION    ((uint32_t)(1 << SENSOR_QUANTITY_WINDDIRECTION))
 | 
			
		||||
#define SENSOR_ABILITY_ALTITUDE ((uint32_t)(1 << SENSOR_QUANTITY_ALTITUDE))
 | 
			
		||||
 | 
			
		||||
struct SensorProductInfo {
 | 
			
		||||
    uint32_t ability;           /* Bitwise OR of sensor ability */
 | 
			
		||||
| 
						 | 
				
			
			@ -96,6 +99,9 @@ enum SensorQuantityType {
 | 
			
		|||
    SENSOR_QUANTITY_CH4,
 | 
			
		||||
    SENSOR_QUANTITY_IAQ,
 | 
			
		||||
    SENSOR_QUANTITY_TVOC,
 | 
			
		||||
    SENSOR_QUANTITY_WINDSPEED,
 | 
			
		||||
    SENSOR_QUANTITY_WINDDIRECTION,
 | 
			
		||||
    SENSOR_QUANTITY_ALTITUDE,
 | 
			
		||||
    /* ...... */
 | 
			
		||||
    SENSOR_QUANTITY_END,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,28 +68,11 @@ static int SensorDeviceOpen(struct SensorDevice *sdev)
 | 
			
		|||
 */
 | 
			
		||||
static int SensorDeviceRead(struct SensorDevice *sdev, size_t len)
 | 
			
		||||
{
 | 
			
		||||
#ifdef ADD_NUTTX_FETURES
 | 
			
		||||
    int ret;
 | 
			
		||||
    ret = PrivRead(sdev->fd, sdev->buffer, len);
 | 
			
		||||
    if (ret != len ){
 | 
			
		||||
        perror("Failed to read data!\n");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
#else
 | 
			
		||||
    //send i2c device start signal and address, need to implemente in OS i2c driver
 | 
			
		||||
    if (PrivWrite(sdev->fd, NULL, 0) != 1)
 | 
			
		||||
        return -1;
 | 
			
		||||
    
 | 
			
		||||
    PrivTaskDelay(50);
 | 
			
		||||
 | 
			
		||||
    //Read i2c device data from i2c device address
 | 
			
		||||
    if (PrivRead(sdev->fd, sdev->buffer, len) != 1)
 | 
			
		||||
    if (PrivRead(sdev->fd, sdev->buffer, len) < 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct SensorDone done =
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
 | 
			
		||||
config SENSOR_QS_FX
 | 
			
		||||
        bool "Using qs-fx wind direction sensor"
 | 
			
		||||
        default n
 | 
			
		||||
 | 
			
		||||
        if SENSOR_QS_FX
 | 
			
		||||
                config SENSOR_DEVICE_QS_FX
 | 
			
		||||
                        string "qs-fx sensor name"
 | 
			
		||||
                        default "qs_fx"
 | 
			
		||||
                
 | 
			
		||||
                config SENSOR_QUANTITY_QS_FX_WINDDIRECTION
 | 
			
		||||
                        string "qs-fx quantity name"
 | 
			
		||||
                        default "winddirection_1"
 | 
			
		||||
                
 | 
			
		||||
                if ADD_XIZI_FETURES
 | 
			
		||||
                        config SENSOR_QS_FX_DRIVER_EXTUART
 | 
			
		||||
                                bool "Using extra uart to support qs-fx"
 | 
			
		||||
                                default y
 | 
			
		||||
 | 
			
		||||
                        config SENSOR_DEVICE_QS_FX_DEV
 | 
			
		||||
                                string "qs-fx device name"
 | 
			
		||||
                                default "/dev/uart2_dev2"
 | 
			
		||||
                                depends on !SENSOR_QS_FX_DRIVER_EXTUART
 | 
			
		||||
 | 
			
		||||
                        if SENSOR_QS_FX_DRIVER_EXTUART
 | 
			
		||||
                                config SENSOR_DEVICE_QS_FX_DEV
 | 
			
		||||
                                        string "qs-fx device extra uart path"
 | 
			
		||||
                                        default "/dev/extuart_dev2"
 | 
			
		||||
                                
 | 
			
		||||
                                config SENSOR_DEVICE_QS_FX_DEV_EXT_PORT
 | 
			
		||||
                                        int "if qs-fx device using extuart, choose port"
 | 
			
		||||
                                        default "2"
 | 
			
		||||
                        endif
 | 
			
		||||
                endif
 | 
			
		||||
 | 
			
		||||
                if ADD_NUTTX_FETURES
 | 
			
		||||
 | 
			
		||||
                endif
 | 
			
		||||
 | 
			
		||||
                if ADD_RTTHREAD_FETURES
 | 
			
		||||
 | 
			
		||||
                endif
 | 
			
		||||
        endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
ifeq ($(CONFIG_SENSOR_QS_FX),y)
 | 
			
		||||
	SRC_DIR += qs-fx
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
import os
 | 
			
		||||
Import('RTT_ROOT')
 | 
			
		||||
from building import *
 | 
			
		||||
 | 
			
		||||
cwd = GetCurrentDir()
 | 
			
		||||
objs = []
 | 
			
		||||
list = os.listdir(cwd)
 | 
			
		||||
 | 
			
		||||
for d in list:
 | 
			
		||||
    path = os.path.join(cwd, d)
 | 
			
		||||
    if os.path.isfile(os.path.join(path, 'SConscript')):
 | 
			
		||||
        objs = objs + SConscript(os.path.join(path, 'SConscript'))
 | 
			
		||||
 | 
			
		||||
Return('objs')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
SRC_FILES := qs-fx.c
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
from building import *
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
cwd = GetCurrentDir()
 | 
			
		||||
src = []
 | 
			
		||||
if GetDepend(['SENSOR_QS_FX']):
 | 
			
		||||
    src += ['qs-fx.c']
 | 
			
		||||
group = DefineGroup('sensor wind direction qs-fx', src, depend = [], CPPPATH = [cwd])
 | 
			
		||||
 | 
			
		||||
Return('group')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,162 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2020 AIIT XUOS Lab
 | 
			
		||||
* XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file qs-fx.c
 | 
			
		||||
 * @brief qs-fx wind direction driver base sensor
 | 
			
		||||
 * @version 1.1
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.12.10
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sensor.h>
 | 
			
		||||
 | 
			
		||||
static struct SensorDevice qs_fx;
 | 
			
		||||
static char instructions[] = {0x02, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x39};
 | 
			
		||||
 | 
			
		||||
static struct SensorProductInfo info =
 | 
			
		||||
{
 | 
			
		||||
    SENSOR_ABILITY_WINDDIRECTION,
 | 
			
		||||
    "清易电子",
 | 
			
		||||
    "QS-FX",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Open QS-FX voice device
 | 
			
		||||
 * @param sdev - sensor device pointer
 | 
			
		||||
 * @return success: 1 , failure: other
 | 
			
		||||
 */
 | 
			
		||||
static int SensorDeviceOpen(struct SensorDevice *sdev)
 | 
			
		||||
{
 | 
			
		||||
    int result = 0;
 | 
			
		||||
 | 
			
		||||
    sdev->fd = PrivOpen(SENSOR_DEVICE_QS_FX_DEV, O_RDWR);
 | 
			
		||||
    if (sdev->fd < 0) {
 | 
			
		||||
        printf("open %s error\n", SENSOR_DEVICE_QS_FX_DEV);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    struct SerialDataCfg cfg;
 | 
			
		||||
    cfg.serial_baud_rate    = BAUD_RATE_9600;
 | 
			
		||||
    cfg.serial_data_bits    = DATA_BITS_8;
 | 
			
		||||
    cfg.serial_stop_bits    = STOP_BITS_1;
 | 
			
		||||
    cfg.serial_buffer_size  = 64;
 | 
			
		||||
    cfg.serial_parity_mode  = PARITY_NONE;
 | 
			
		||||
    cfg.serial_bit_order    = 0;
 | 
			
		||||
    cfg.serial_invert_mode  = 0;
 | 
			
		||||
#ifdef SENSOR_QS_FX_DRIVER_EXTUART    
 | 
			
		||||
    cfg.ext_uart_no         = SENSOR_DEVICE_QS_FX_DEV_EXT_PORT;
 | 
			
		||||
    cfg.port_configure      = PORT_CFG_INIT;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    struct PrivIoctlCfg ioctl_cfg;
 | 
			
		||||
    ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
 | 
			
		||||
    ioctl_cfg.args = &cfg;
 | 
			
		||||
    result = PrivIoctl(sdev->fd, OPE_INT, &ioctl_cfg);
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Read sensor device
 | 
			
		||||
 * @param sdev - sensor device pointer
 | 
			
		||||
 * @param len - the length of the read data
 | 
			
		||||
 * @return get data length
 | 
			
		||||
 */
 | 
			
		||||
static int SensorDeviceRead(struct SensorDevice *sdev, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    if (PrivWrite(sdev->fd, instructions, sizeof(instructions)) < 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
    
 | 
			
		||||
    if (PrivRead(sdev->fd, sdev->buffer, len) < 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct SensorDone done =
 | 
			
		||||
{
 | 
			
		||||
    SensorDeviceOpen,
 | 
			
		||||
    NULL,
 | 
			
		||||
    SensorDeviceRead,
 | 
			
		||||
    NULL,
 | 
			
		||||
    NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Init QS-FX sensor and register
 | 
			
		||||
 * @return void
 | 
			
		||||
 */
 | 
			
		||||
static void QsFxInit(void)
 | 
			
		||||
{
 | 
			
		||||
    qs_fx.name = SENSOR_DEVICE_QS_FX;
 | 
			
		||||
    qs_fx.info = &info;
 | 
			
		||||
    qs_fx.done = &done;
 | 
			
		||||
    qs_fx.status = SENSOR_DEVICE_PASSIVE;
 | 
			
		||||
 | 
			
		||||
    SensorDeviceRegister(&qs_fx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static struct SensorQuantity qs_fx_wind_direction;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Analysis QS-FX wind direction
 | 
			
		||||
 * @param quant - sensor quantity pointer
 | 
			
		||||
 * @return quantity value
 | 
			
		||||
 */
 | 
			
		||||
static int32_t ReadWindDirection(struct SensorQuantity *quant)
 | 
			
		||||
{
 | 
			
		||||
    if (!quant)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    short result;
 | 
			
		||||
    if (quant->sdev->done->read != NULL) {
 | 
			
		||||
        if (quant->sdev->status == SENSOR_DEVICE_PASSIVE) {
 | 
			
		||||
            quant->sdev->done->read(quant->sdev, 6);
 | 
			
		||||
            result = (quant->sdev->buffer[3] << 8) | quant->sdev->buffer[4];
 | 
			
		||||
 | 
			
		||||
            return (int32_t)result;
 | 
			
		||||
        }
 | 
			
		||||
        if (quant->sdev->status == SENSOR_DEVICE_ACTIVE) {
 | 
			
		||||
            printf("Please set passive mode.\n");
 | 
			
		||||
        }
 | 
			
		||||
    }else{
 | 
			
		||||
        printf("%s don't have read done.\n", quant->name);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Init QS-FX voice quantity and register
 | 
			
		||||
 * @return 0
 | 
			
		||||
 */
 | 
			
		||||
int QsFxWindDirectionInit(void)
 | 
			
		||||
{
 | 
			
		||||
    QsFxInit();
 | 
			
		||||
    
 | 
			
		||||
    qs_fx_wind_direction.name = SENSOR_QUANTITY_QS_FX_WINDDIRECTION;
 | 
			
		||||
    qs_fx_wind_direction.type = SENSOR_QUANTITY_WINDDIRECTION;
 | 
			
		||||
    qs_fx_wind_direction.value.decimal_places = 1;
 | 
			
		||||
    qs_fx_wind_direction.value.max_std = 600;
 | 
			
		||||
    qs_fx_wind_direction.value.min_std = 0;
 | 
			
		||||
    qs_fx_wind_direction.value.last_value = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
    qs_fx_wind_direction.value.max_value = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
    qs_fx_wind_direction.value.min_value = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
    qs_fx_wind_direction.sdev = &qs_fx;
 | 
			
		||||
    qs_fx_wind_direction.ReadValue = ReadWindDirection;
 | 
			
		||||
 | 
			
		||||
    SensorQuantityRegister(&qs_fx_wind_direction);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
 | 
			
		||||
config SENSOR_QS_FS
 | 
			
		||||
        bool "Using qs-fs wind speed sensor"
 | 
			
		||||
        default n
 | 
			
		||||
 | 
			
		||||
        if SENSOR_QS_FS
 | 
			
		||||
                config SENSOR_DEVICE_QS_FS
 | 
			
		||||
                        string "qs-fs sensor name"
 | 
			
		||||
                        default "qs-fs"
 | 
			
		||||
                
 | 
			
		||||
                config SENSOR_QUANTITY_QS_FS_WINDSPEED
 | 
			
		||||
                        string "qs-fs quantity name"
 | 
			
		||||
                        default "windspeed_1"
 | 
			
		||||
                
 | 
			
		||||
                if ADD_XIZI_FETURES
 | 
			
		||||
                        config SENSOR_QS_FS_DRIVER_EXTUART
 | 
			
		||||
                                bool "Using extra uart to support qs-fx"
 | 
			
		||||
                                default y
 | 
			
		||||
 | 
			
		||||
                        config SENSOR_DEVICE_QS_FS_DEV
 | 
			
		||||
                                string "qs-fx device name"
 | 
			
		||||
                                default "/dev/uart2_dev2"
 | 
			
		||||
                                depends on !SENSOR_QS_FS_DRIVER_EXTUART
 | 
			
		||||
 | 
			
		||||
                        if SENSOR_QS_FS_DRIVER_EXTUART
 | 
			
		||||
                                config SENSOR_DEVICE_QS_FS_DEV
 | 
			
		||||
                                        string "qs-fx device extra uart path"
 | 
			
		||||
                                        default "/dev/extuart_dev7"
 | 
			
		||||
                                
 | 
			
		||||
                                config SENSOR_DEVICE_QS_FS_DEV_EXT_PORT
 | 
			
		||||
                                        int "if qs-fx device using extuart, choose port"
 | 
			
		||||
                                        default "7"
 | 
			
		||||
                        endif
 | 
			
		||||
                endif
 | 
			
		||||
 | 
			
		||||
                if ADD_NUTTX_FETURES
 | 
			
		||||
 | 
			
		||||
                endif
 | 
			
		||||
 | 
			
		||||
                if ADD_RTTHREAD_FETURES
 | 
			
		||||
 | 
			
		||||
                endif
 | 
			
		||||
        endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
ifeq ($(CONFIG_SENSOR_QS_FS),y)
 | 
			
		||||
	SRC_DIR += qs-fs
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
import os
 | 
			
		||||
Import('RTT_ROOT')
 | 
			
		||||
from building import *
 | 
			
		||||
 | 
			
		||||
cwd = GetCurrentDir()
 | 
			
		||||
objs = []
 | 
			
		||||
list = os.listdir(cwd)
 | 
			
		||||
 | 
			
		||||
for d in list:
 | 
			
		||||
    path = os.path.join(cwd, d)
 | 
			
		||||
    if os.path.isfile(os.path.join(path, 'SConscript')):
 | 
			
		||||
        objs = objs + SConscript(os.path.join(path, 'SConscript'))
 | 
			
		||||
 | 
			
		||||
Return('objs')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
SRC_FILES := qs-fs.c
 | 
			
		||||
 | 
			
		||||
include $(KERNEL_ROOT)/compiler.mk
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
from building import *
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
cwd = GetCurrentDir()
 | 
			
		||||
src = []
 | 
			
		||||
if GetDepend(['SENSOR_QS_FS']):
 | 
			
		||||
    src += ['qs-fs.c']
 | 
			
		||||
group = DefineGroup('sensor wind speed qs-fs', src, depend = [], CPPPATH = [cwd])
 | 
			
		||||
 | 
			
		||||
Return('group')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,162 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) 2020 AIIT XUOS Lab
 | 
			
		||||
* XiUOS is licensed under Mulan PSL v2.
 | 
			
		||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
			
		||||
* You may obtain a copy of Mulan PSL v2 at:
 | 
			
		||||
*        http://license.coscl.org.cn/MulanPSL2
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
			
		||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
			
		||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
			
		||||
* See the Mulan PSL v2 for more details.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file qs-fs.c
 | 
			
		||||
 * @brief qs-fs wind speed driver base sensor
 | 
			
		||||
 * @version 1.1
 | 
			
		||||
 * @author AIIT XUOS Lab
 | 
			
		||||
 * @date 2021.12.10
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sensor.h>
 | 
			
		||||
 | 
			
		||||
static struct SensorDevice qs_fs;
 | 
			
		||||
static const unsigned char instructions[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A};
 | 
			
		||||
 | 
			
		||||
static struct SensorProductInfo info =
 | 
			
		||||
{
 | 
			
		||||
    SENSOR_ABILITY_WINDSPEED,
 | 
			
		||||
    "清易电子",
 | 
			
		||||
    "QS-FS",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Open QS-FS voice device
 | 
			
		||||
 * @param sdev - sensor device pointer
 | 
			
		||||
 * @return success: 1 , failure: other
 | 
			
		||||
 */
 | 
			
		||||
static int SensorDeviceOpen(struct SensorDevice *sdev)
 | 
			
		||||
{
 | 
			
		||||
    int result = 0;
 | 
			
		||||
 | 
			
		||||
    sdev->fd = PrivOpen(SENSOR_DEVICE_QS_FS_DEV, O_RDWR);
 | 
			
		||||
    if (sdev->fd < 0) {
 | 
			
		||||
        printf("open %s error\n", SENSOR_DEVICE_QS_FS_DEV);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    struct SerialDataCfg cfg;
 | 
			
		||||
    cfg.serial_baud_rate    = BAUD_RATE_9600;
 | 
			
		||||
    cfg.serial_data_bits    = DATA_BITS_8;
 | 
			
		||||
    cfg.serial_stop_bits    = STOP_BITS_1;
 | 
			
		||||
    cfg.serial_buffer_size  = 64;
 | 
			
		||||
    cfg.serial_parity_mode  = PARITY_NONE;
 | 
			
		||||
    cfg.serial_bit_order    = 0;
 | 
			
		||||
    cfg.serial_invert_mode  = 0;
 | 
			
		||||
#ifdef SENSOR_QS_FS_DRIVER_EXTUART    
 | 
			
		||||
    cfg.ext_uart_no         = SENSOR_DEVICE_QS_FS_DEV_EXT_PORT;
 | 
			
		||||
    cfg.port_configure      = PORT_CFG_INIT;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    struct PrivIoctlCfg ioctl_cfg;
 | 
			
		||||
    ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
 | 
			
		||||
    ioctl_cfg.args = &cfg;
 | 
			
		||||
    result = PrivIoctl(sdev->fd, OPE_INT, &ioctl_cfg);
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Read sensor device
 | 
			
		||||
 * @param sdev - sensor device pointer
 | 
			
		||||
 * @param len - the length of the read data
 | 
			
		||||
 * @return get data length
 | 
			
		||||
 */
 | 
			
		||||
static int SensorDeviceRead(struct SensorDevice *sdev, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    if (PrivWrite(sdev->fd, instructions, sizeof(instructions)) < 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
    
 | 
			
		||||
    if (PrivRead(sdev->fd, sdev->buffer, len) < 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct SensorDone done =
 | 
			
		||||
{
 | 
			
		||||
    SensorDeviceOpen,
 | 
			
		||||
    NULL,
 | 
			
		||||
    SensorDeviceRead,
 | 
			
		||||
    NULL,
 | 
			
		||||
    NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Init QS-FS sensor and register
 | 
			
		||||
 * @return void
 | 
			
		||||
 */
 | 
			
		||||
static void QsFsInit(void)
 | 
			
		||||
{
 | 
			
		||||
    qs_fs.name = SENSOR_DEVICE_QS_FS;
 | 
			
		||||
    qs_fs.info = &info;
 | 
			
		||||
    qs_fs.done = &done;
 | 
			
		||||
    qs_fs.status = SENSOR_DEVICE_PASSIVE;
 | 
			
		||||
 | 
			
		||||
    SensorDeviceRegister(&qs_fs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static struct SensorQuantity qs_fs_wind_speed;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Analysis QS-FS wind speed
 | 
			
		||||
 * @param quant - sensor quantity pointer
 | 
			
		||||
 * @return quantity value
 | 
			
		||||
 */
 | 
			
		||||
static int32_t ReadWindSpeed(struct SensorQuantity *quant)
 | 
			
		||||
{
 | 
			
		||||
    if (!quant)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    short result;
 | 
			
		||||
    if (quant->sdev->done->read != NULL) {
 | 
			
		||||
        if (quant->sdev->status == SENSOR_DEVICE_PASSIVE) {
 | 
			
		||||
            quant->sdev->done->read(quant->sdev, 6);
 | 
			
		||||
            result = (quant->sdev->buffer[3] << 8) | quant->sdev->buffer[4];
 | 
			
		||||
 | 
			
		||||
            return (int32_t)result;
 | 
			
		||||
        }
 | 
			
		||||
        if (quant->sdev->status == SENSOR_DEVICE_ACTIVE) {
 | 
			
		||||
            printf("Please set passive mode.\n");
 | 
			
		||||
        }
 | 
			
		||||
    }else{
 | 
			
		||||
        printf("%s don't have read done.\n", quant->name);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description: Init QS-FS voice quantity and register
 | 
			
		||||
 * @return 0
 | 
			
		||||
 */
 | 
			
		||||
int QsFsWindSpeedInit(void)
 | 
			
		||||
{
 | 
			
		||||
    QsFsInit();
 | 
			
		||||
    
 | 
			
		||||
    qs_fs_wind_speed.name = SENSOR_QUANTITY_QS_FS_WINDSPEED;
 | 
			
		||||
    qs_fs_wind_speed.type = SENSOR_QUANTITY_WINDSPEED;
 | 
			
		||||
    qs_fs_wind_speed.value.decimal_places = 1;
 | 
			
		||||
    qs_fs_wind_speed.value.max_std = 600;
 | 
			
		||||
    qs_fs_wind_speed.value.min_std = 0;
 | 
			
		||||
    qs_fs_wind_speed.value.last_value = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
    qs_fs_wind_speed.value.max_value = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
    qs_fs_wind_speed.value.min_value = SENSOR_QUANTITY_VALUE_ERROR;
 | 
			
		||||
    qs_fs_wind_speed.sdev = &qs_fs;
 | 
			
		||||
    qs_fs_wind_speed.ReadValue = ReadWindSpeed;
 | 
			
		||||
 | 
			
		||||
    SensorQuantityRegister(&qs_fs_wind_speed);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -27,6 +27,7 @@
 | 
			
		|||
#include <nuttx/time.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <nuttx/wireless/lpwan/sx127x.h>
 | 
			
		||||
 | 
			
		||||
typedef uint8_t uint8;
 | 
			
		||||
typedef uint16_t uint16;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -141,6 +141,7 @@ static int PrivSerialIoctl(int fd, int cmd, void *args)
 | 
			
		|||
    config.bufsz = RT_SERIAL_RB_BUFSZ;
 | 
			
		||||
    config.parity = serial_cfg->serial_parity_mode;
 | 
			
		||||
    config.invert = serial_cfg->serial_invert_mode;
 | 
			
		||||
    config.reserved = serial_cfg->ext_uart_no; ///< using extuart port number
 | 
			
		||||
    rt_fd = fd_get(fd);
 | 
			
		||||
    ret =  rt_fd->fops->ioctl(rt_fd, RT_DEVICE_CTRL_CONFIG, &config);
 | 
			
		||||
    return ret;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,4 +12,5 @@ menu "lib"
 | 
			
		|||
     source "$APP_DIR/lib/cJSON/Kconfig"
 | 
			
		||||
	 source "$APP_DIR/lib/queue/Kconfig"
 | 
			
		||||
     source "$APP_DIR/lib/lvgl/Kconfig"
 | 
			
		||||
     source "$APP_DIR/lib/embedded_database/Kconfig"
 | 
			
		||||
endmenu
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
menuconfig USING_EMBEDDED_DATABASE
 | 
			
		||||
    bool "embedded database"
 | 
			
		||||
    default n
 | 
			
		||||
if USING_EMBEDDED_DATABASE
 | 
			
		||||
        source "$APP_DIR/lib/embedded_database/flashdb/Kconfig"
 | 
			
		||||
endif
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue