openwrt開發筆記三:uci移植及API調用


1.uci編譯安裝、移植

安裝依賴 libubox

#安裝cmake
sudo apt-get install cmake
#下載依賴庫libubox
git clone http://git.nbd.name/luci2/libubox.git
git clone https://git.openwrt.org/project/libubox.git
#安裝libubox,先安裝到ubuntu同時制作一份安裝庫
cd libubox
mkdir build install
cd build
cmake .. -DBUILD_LUA=off -DBUILD_EXAMPLES=off
sudo make install
#ubuntu庫安裝完畢,開始制作目標庫
#刪除build目錄所有文件,指定交叉編譯工具和安裝目錄
sudo rm -rf *
cmake .. -DBUILD_LUA=off -DBUILD_EXAMPLES=off -DCMAKE_INSTALL_PREFIX=../install  -DCMAKE_C_COMPILER=/home/wangh/workspace/openwrt/PandoraBox-SDK-qualcomm-ipq40xx_gcc-4.9-linaro_uClibc-1.0.x_eabi.Linux-x86_64/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-4.9-linaro_uClibc-1.0.x_eabi/bin/arm-openwrt-linux-gcc
#安裝到交叉編譯庫中
sudo rm -rf *
cmake .. -DBUILD_LUA=off -DBUILD_EXAMPLES=off -DCMAKE_INSTALL_PREFIX=/home/wangh/workspace/openwrt/PandoraBox-SDK-qualcomm-ipq40xx_gcc-4.9-linaro_uClibc-1.0.x_eabi.Linux-x86_64/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-4.9-linaro_uClibc-1.0.x_eabi/usr  -DCMAKE_C_COMPILER=/home/wangh/workspace/openwrt/PandoraBox-SDK-qualcomm-ipq40xx_gcc-4.9-linaro_uClibc-1.0.x_eabi.Linux-x86_64/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-4.9-linaro_uClibc-1.0.x_eabi/bin/arm-openwrt-linux-gcc

make install

安裝uci

#下載uci源碼
git clone https://git.openwrt.org/project/uci.git
#安裝libubox,先安裝到ubuntu同時制作一份安裝庫
cd uci
mkdir build install
cd build
cmake .. -DBUILD_LUA=off
sudo make install
#ubuntu庫安裝完畢,開始制作目標庫
#刪除build目錄所有文件,指定交叉編譯工具和安裝目錄
sudo rm -rf *
cmake .. -DBUILD_LUA=off -DCMAKE_INSTALL_PREFIX=../install  -DCMAKE_C_COMPILER=/home/wangh/workspace/openwrt/PandoraBox-SDK-qualcomm-ipq40xx_gcc-4.9-linaro_uClibc-1.0.x_eabi.Linux-x86_64/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-4.9-linaro_uClibc-1.0.x_eabi/bin/arm-openwrt-linux-gcc
#交叉編譯安裝到交叉編譯庫目錄
sudo rm -rf *
cmake .. -DBUILD_LUA=off -DCMAKE_INSTALL_PREFIX=/home/wangh/workspace/openwrt/PandoraBox-SDK-qualcomm-ipq40xx_gcc-4.9-linaro_uClibc-1.0.x_eabi.Linux-x86_64/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-4.9-linaro_uClibc-1.0.x_eabi/usr  -DCMAKE_C_COMPILER=/home/wangh/workspace/openwrt/PandoraBox-SDK-qualcomm-ipq40xx_gcc-4.9-linaro_uClibc-1.0.x_eabi.Linux-x86_64/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-4.9-linaro_uClibc-1.0.x_eabi/bin/arm-openwrt-linux-gcc

2.C調用uci

配置示例文件 /etc/config/gateway

config interface 'netconf'
	option serverurl '10.99.20.33/gateway'
	option loaclip '192.168.11.3'
	option netmask '255.255.255.0'
	option gateway '192.168.11.1'
	option proto 'static'
	option dns '10.55.33.2'
	option serverip '10.99.20.100'
	option serverport '8000'

config device
	option devstate '0'
	option devid '001'
	option devtype '網關'
	option devmodel 'GW-001'
	option devposition '武漢'
	option enable 'yes'

config rs485
	option name 'COM1'
	option baudrate '9600'
	option databit '8'
	option stopbit '1'
	option parity 'n'
	option enable 'yes'

config device
	option devstate '0'
	option devid '002'
	option devtype '單燈控制器'
	option devmodel 'LIGHT-001'
	option devposition '武漢'
	option enable 'yes'

config device
	option devstate '0'
	option devid '003'
	option devtype '單燈控制器'
	option devmodel 'LIGHT-001'
	option devposition '武漢'
	option enable 'yes'

代碼示例

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include "uci.h"
#include "config.h"

#define UCI_CONFIG_FILE "/etc/config/gateway"

/**
 * @brief 獲取配置信息
 * @param  section	配置段名稱
 * @param  option 	配置項
 * @param  pdata  	獲取的配置內容
 * @param  plen  	獲取的配置內容長度
 * @return int 		成功返回UCI_OK, 失敗返回其它值
 */
int config_get(char *section, char *option, unsigned char *pdata, unsigned short *plen)
{
	int ret = UCI_OK;
	struct uci_package * pkg = NULL;
	const char *value;

	ctx = uci_alloc_context(); 	// 申請一個UCI上下文.
	if (!ctx) {
		return UCI_ERR_MEM;
	}

	ret = uci_load(ctx, UCI_CONFIG_FILE, &pkg);		// 加載並解析配置文件
	if(ret != UCI_OK)
    {
        uci_free_context(ctx);
        return ret;
    }

	struct uci_section *s = uci_lookup_section(ctx, pkg, section);
	if(s != NULL)
	{
		if (NULL != (value = uci_lookup_option_string(ctx, s, option)))
		{
//			pdata = (unsigned char *)strdup(value);
			strncpy(pdata, value, 100);
			*plen = strlen(pdata);
		}
		else
		{
			uci_unload(ctx, pkg);
			uci_free_context(ctx);
			ctx = NULL;
			return UCI_ERR_NOTFOUND;
		}
	}
	else
	{
		uci_unload(ctx, pkg);
		uci_free_context(ctx);
		ctx = NULL;
		return UCI_ERR_NOTFOUND;
	}

	uci_unload(ctx, pkg);
	uci_free_context(ctx);
	ctx = NULL;
	return ret;
}

/**
 * @brief 設置配置信息
 * @param  section 	配置段名稱
 * @param  option  	配置項
 * @param  pdata  	獲取的配置內容
 * @param  plen    	獲取的配置內容長度
 * @return int		成功返回UCI_OK, 失敗返回其它值
 */
int config_set(char *section, char *option, unsigned char *pdata, unsigned short *plen)
{
	struct uci_package * pkg = NULL;
	struct uci_element *e;
	int ret = UCI_OK;

	ctx = uci_alloc_context();
	if (!ctx) {
		return UCI_ERR_MEM;
	}

	struct uci_ptr ptr ={
				.package = "gateway",
				.section = section,
				.option = option,
				.value = pdata,
			};

	ret = uci_set(ctx, &ptr);	//寫入配置
    if(ret != UCI_OK)
    {
        uci_free_context(ctx);
        return ret;
    }

	ret = uci_save(ctx, ptr.p);	//保存更改
    if(ret != UCI_OK)
    {
        uci_free_context(ctx);
        return ret;
    }

    ret = uci_commit(ctx, &ptr.p, false);	//提交更改
    if(ret != UCI_OK)
    {
        uci_free_context(ctx);
        return ret;
    }

	// system("/etc/init.d/network restart");	//配置應用示例

	uci_free_context(ctx);
    return ret;
}

/**
 * @brief 獲取配置項值
 * @param  o      	配置項
 * @param  out   	獲取的配置內容
 * @return int		成功返回UCI_OK, 失敗返回其它值
 */
static int uci_get_value(struct uci_option *o, char *out)
{
	struct uci_element *e;
    const char *delimiter = " ";	//值為列表時的分隔符
	bool sep = false;

	switch(o->type) {
	case UCI_TYPE_STRING:
        strcpy(out, o->v.string);
		break;
	case UCI_TYPE_LIST:
		uci_foreach_element(&o->v.list, e) {
            if(sep)
                strcat(out, delimiter);
            strcat(out, e->name);
			sep = true;
		}
		break;
	default:
		return UCI_ERR_INVAL;
		break;
	}

    return UCI_OK;
}

/**
 * @brief 獲取uci配置項
 * @param  arg	獲取該參數下的值
 *         eg: gateway.@interface[0]
 *             gateway.interface0.serverport
 * @param  out	獲取的值存儲區
 * @return int 	成功返回UCI_OK, 失敗返回其它值
 */
int uci_get_str(const char *arg, char *out)
{
    struct uci_context *ctx;
    struct uci_element *e;
	struct uci_ptr ptr;
	int ret = UCI_OK;
    char *name = NULL;

    if(arg == NULL || out == NULL) return UCI_ERR_INVAL;
    name = strdup(arg);
    if(name == NULL) return UCI_ERR_INVAL;

    ctx = uci_alloc_context();
	if (!ctx) {
        free(name);
		return UCI_ERR_MEM;
	}

    if (uci_lookup_ptr(ctx, &ptr, name, true) != UCI_OK) {
        uci_free_context(ctx);
        free(name);
		return UCI_ERR_NOTFOUND;
	}

    if(UCI_LOOKUP_COMPLETE & ptr.flags)
    {
        e = ptr.last;
        switch(e->type)
        {
            case UCI_TYPE_SECTION:
                ret = UCI_ERR_INVAL;
            break;
            case UCI_TYPE_OPTION:
                ret = uci_get_value(ptr.o, out);
            break;
            default:
                ret = UCI_ERR_NOTFOUND;
            break;
        }
    }
    else
        ret = UCI_ERR_NOTFOUND;

    uci_free_context(ctx);
    free(name);
    return ret;
}

/**
 * @brief 設置uci配置項 , 保存並且提交更改到文件
 * @param  arg	設置參數
 *         eg: gateway.@interface[0]=wifi-iface
 *             gateway.interface0.serverip=10.99.20.100
 *             gateway.interface0.serverport=8000
 * @return int 	成功返回UCI_OK, 失敗返回其它值
 */
int uci_set_str(const char *arg)
{
    struct uci_context *ctx;
    struct uci_element *e;
	struct uci_ptr ptr;
	int ret = UCI_OK;
    char *name = NULL;

    if(arg == NULL) return UCI_ERR_INVAL;
    name = strdup(arg);
    if(name == NULL) return UCI_ERR_MEM;

    ctx = uci_alloc_context();
	if (!ctx) {
        free(name);
		return UCI_ERR_MEM;
	}

    if (uci_lookup_ptr(ctx, &ptr, name, true) != UCI_OK) {
        uci_free_context(ctx);
        free(name);
		return UCI_ERR_NOTFOUND;
	}

    ret = uci_set(ctx, &ptr);
    if(ret != UCI_OK)
    {
        uci_free_context(ctx);
        free(name);
        return ret;
    }

    ret = uci_save(ctx, ptr.p);
    if(ret != UCI_OK)
    {
        uci_free_context(ctx);
        free(name);
        return ret;
    }

    ret = uci_commit(ctx, &ptr.p, false);
    if(ret != UCI_OK)
    {
        uci_free_context(ctx);
        free(name);
        return ret;
    }

    uci_free_context(ctx);
    free(name);
    return ret;
}

測試用例 config_test.c

int main(void)
{
    printf("Hello World!\n");
    char tmp[100];
    unsigned short tmplen;
    int rc = config_get("netconf", "serverip", tmp, &tmplen);
    printf("serverip is %s --%d --%d\n", tmp,  tmplen, rc);

    rc = config_get("netconf", "serverport", tmp, &tmplen);
	printf("serverport is %s --%d --%d\n", tmp, tmplen, rc);

	rc = config_set("netconf", "serverport", "8000", &tmplen);
	printf("serverport set --%d\n", rc);

	rc = config_get("netconf", "serverport", tmp, &tmplen);
	printf("serverport is %s --%d --%d\n", tmp, tmplen, rc);

    rc =  uci_get_str("gateway.netconf.serverport", tmp);
    printf("serverport is %s --%d\n", tmp,  rc);

    rc =  uci_set_str("gateway.netconf.serverport=9000");
    printf("serverport set --%d\n", rc);

    rc =  uci_get_str("gateway.netconf.serverport", tmp);
    printf("serverport is %s --%d\n", tmp,  rc);

    return 0;
}

用例 Makefile

TOOLCHAIN_DIR = "/home/wangh/workspace/openwrt/PandoraBox-SDK-qualcomm-ipq40xx_gcc-4.9-linaro_uClibc-1.0.x_eabi.Linux-x86_64/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-4.9-linaro_uClibc-1.0.x_eabi"

BIN := config_test
OBJS := config_test.o
OBJS += config.o

all:$(OBJS) $(BIN) 

$(OBJS):%.o:%.c
	$(CC) $(CFLAGS) -I $(TOOLCHAIN_DIR)/usr/include/ -c $^ -o $@

$(BIN):$(OBJS)
	$(CC) -o $@ $^ $(LDFLAGS) -L $(TOOLCHAIN_DIR)/usr/lib -luci

clean: 
	rm -f *.o $(BIN)

3.lua調用uci

#!usr/bin/lua
require("uci")

-- uci測試
x = uci.cursor() --uci上下文
local serverip = x:get("gateway", "netconf", "serverip")
print(serverip)

x:foreach(
	"gateway",
	"device",
	function(s)
		if s.devid == "002" then
			print("------------------")
			for key, value in pairs(s) do
				print(key .. ": " .. tostring(value))
			end
		end
	end
)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM