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
)
posted @ 2019-12-18 20:02  silencehuan  阅读(5276)  评论(0编辑  收藏  举报