openwrt Development Notes three: uci migration and API calls

1.uci compiler installation, migration

Installation depends 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

Installation 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 call uci

Configuration example file / 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'

The sample code

#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;
}

Test 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;
}

Examples 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 call 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
)

Guess you like

Origin www.cnblogs.com/silencehuan/p/12061817.html