• 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!
    ");
        char tmp[100];
        unsigned short tmplen;
        int rc = config_get("netconf", "serverip", tmp, &tmplen);
        printf("serverip is %s --%d --%d
    ", tmp,  tmplen, rc);
    
        rc = config_get("netconf", "serverport", tmp, &tmplen);
    	printf("serverport is %s --%d --%d
    ", tmp, tmplen, rc);
    
    	rc = config_set("netconf", "serverport", "8000", &tmplen);
    	printf("serverport set --%d
    ", rc);
    
    	rc = config_get("netconf", "serverport", tmp, &tmplen);
    	printf("serverport is %s --%d --%d
    ", tmp, tmplen, rc);
    
        rc =  uci_get_str("gateway.netconf.serverport", tmp);
        printf("serverport is %s --%d
    ", tmp,  rc);
    
        rc =  uci_set_str("gateway.netconf.serverport=9000");
        printf("serverport set --%d
    ", rc);
    
        rc =  uci_get_str("gateway.netconf.serverport", tmp);
        printf("serverport is %s --%d
    ", 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
    )
    
  • 相关阅读:
    android 模拟器手机如何添加文件到sd卡?
    Asp.Net 前台和后台交互的一些问题
    Cannot get WiFi AP state 错误
    MediaPlayer.getCurrentPosition IllegalStateException错误
    SQL Compare 错误 给定关键字不在字典中
    java.net.SocketException: Connection timed out的一种情况
    System services not available to Activities before onCreate()
    java.net.SocketException: Connection reset by peer
    卸载Microsoft Virtual WiFi Miniport Adapter 方法
    java 跳出 if
  • 原文地址:https://www.cnblogs.com/silencehuan/p/12061817.html
Copyright © 2020-2023  润新知