openwrt ubus简介以及libubus开发说明

  • Post author:
  • Post category:其他





转载:

http://gofly.blog.51cto.com/4344767/1685199





简介

ubus是新openwrt引入的一个消息总线,主要作用是实现不同应用程序之间的信息交互。

ubus启动后会在后台运行ubusd进程,该进程监听一个unix套接字用于与其他应用程序通信。其他应用程序可基于libubox提供的接口(或自己实现)与其通信。

使用ubus的方式主要有:1、向其注册消息或控制接口。2、向其调用其他应用程序的消息或控制接口。3、向其注册监听关心的事件。4、向其发送事件消息。



ubus命令使用说明

ubus命令用于控制调试相关ubus接口,主要命令说明如下:

– list [<path>]                        List objects

– call <path> <method> [<message>]     Call an object method

– listen [<path>…]                   Listen for events

– send <type> [<message>]              Send an event

– wait_for <object> [<object>…]      Wait for multiple objects to appear on ubus



ubus list [-v]

该命令用于显示当前ubus中注册的接口,其中-v参数用以显示各个接口的详细信息。示例如下:

1
2
3
4
5
6
7

ubus list -


v

'dhcp'


@26b45f5d



"ipv4leases"


:{}



"ipv6leases"


:{}

'hostapd.wlan0'


@5e03d420



"get_clients"


:{}



"del_client"


:{



"addr"


:


"String"


,


"reason"


:


"Integer"


,


"deauth"


:


"Boolean"


,


"ban_time"


:


"Integer"


}


ubus call

该命令用于调用ubus中当前注册的接口。示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

ubus call dhcp ipv6leases

{




"device"


: {




"br-lan"


: {




"leases"


: [



{




"duid"


:


"0001000119660ee***4e543***3c70"


,



"iaid"


: 3***72***5,



"hostname"


:


"*******-PC"


,



"assigned"


: 3900,



"length"


: 128,



"ipv6"


: [



"fd23:a6ed:f19b::f3c"



],



"valid"


: -38000



}



]



}



}

}


ubus listen

用于监听ubus相关事件,如果不指定事件名则监听所有事件。(支持通配符*)


ubus send

用于发送事件


ubus wait_for

用于等待指定项的注册到ubus中。



libubus开发说明

libubus与需要与libubox配合使用,先贴出调用libubus的实例代码。



ubus.h

1
2
3
4
5
6
7
8
9
10
11
12
13

#ifndef UBUS_H_

#define UBUS_H_

#include <libubox/blob.h>

int


ubus_send(


const


char


*type,


struct


blob_attr *data);

int


ubus_call(


const


char


*path,


const


char


*method,



struct


blob_attr *data,


struct


blob_attr **ret);

int


ubus_init(


void


);

void


ubus_destory();

#endif



ubus.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294

#include <stdio.h>

#include <errno.h>

#include <unistd.h>

#include <string.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <libubus.h>

#include <libubox/uloop.h>

#include <libubox/blobmsg_json.h>

#include <arpa/inet.h>

#include "ubus.h"

#include "test.h"

#include "debug.h"

#include "pubinfo.h"

struct


ubus_context *ubus_ctx = NULL;

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

enum


{GET_TYPE_FLOW, GET_TYPE_SPEED};

#define _unused __attribute__((unused))

#define _packed __attribute__((packed))

static


struct


blob_buf b;

/**********************************************************************



* pub policy



*********************************************************************/

enum


{




UBUS_test_PUB_TOPIC,



UBUS_test_PUB_MSG,



__UBUS_test_PUB_MAX

};

static


const


struct


blobmsg_policy test_pub_policy[] ={




[UBUS_test_PUB_TOPIC] = { .name =


"topic"


, .type = BLOBMSG_TYPE_STRING },



[UBUS_test_PUB_MSG]   = { .name =


"msg"


,   .type = BLOBMSG_TYPE_TABLE },

};

/**********************************************************************



* Stats policy



*********************************************************************/

enum


{




UBUS_STATS_OBJS,



__UBUS_STATS_MAX

};

static


const


struct


blobmsg_policy stats_pub_policy[] ={




[UBUS_STATS_OBJS] = { .name =


"obj"


, .type = BLOBMSG_TYPE_ARRAY },

};

/**********************************************************************



* sub policy



*********************************************************************/

enum


{




UBUS_test_SUB_TOPICS,



__UBUS_test_SUB_MAX

};

static


const


struct


blobmsg_policy test_sub_policy[] ={




[UBUS_test_SUB_TOPICS] = { .name =


"topics"


, .type = BLOBMSG_TYPE_ARRAY },

};

/**********************************************************************



* subscribe method: subscribe a list of topics



*********************************************************************/

static


int


ubus_test_sub(


struct


ubus_context *ctx,


struct


ubus_object *obj,



struct


ubus_request_data *req,


const


char


*method,



struct


blob_attr *msg)

{




unsigned ret=0;



struct


blob_attr *tb[__UBUS_test_SUB_MAX];



blobmsg_parse(test_sub_policy, __UBUS_test_SUB_MAX, tb, blob_data(msg), blob_len(msg));



if


(!tb[UBUS_test_SUB_TOPICS]){




debug(MSG_ERROR,


"ubus test sub: no arguments!"


);



goto


out;



}



update_test_topic_list(tb[UBUS_test_SUB_TOPICS]);



ret=1;

out:



blob_buf_init(&b, 0);



blobmsg_add_u8(&b,


"result"


, ret);



ubus_send_reply(ctx, req, b.head);



return


0;

}

/**********************************************************************



* publish method: publish messages



*********************************************************************/

static


int


ubus_test_pub(


struct


ubus_context *ctx,


struct


ubus_object *obj,



struct


ubus_request_data *req,


const


char


*method,



struct


blob_attr *msg)

{




int


ret=0;



struct


blob_attr *tb[__UBUS_test_PUB_MAX];



char


*message=


""


, *topic;



blobmsg_parse(test_pub_policy, __UBUS_test_PUB_MAX, tb, blob_data(msg), blob_len(msg));



if


(!tb[UBUS_test_PUB_TOPIC]) {




goto


out;



}



topic=blobmsg_get_string(tb[UBUS_test_PUB_TOPIC]);



if


(tb[UBUS_test_PUB_MSG]!=NULL) {




message=(


char


*)blobmsg_data(tb[UBUS_test_PUB_MSG]);



}



test_pub_msg(topic, message);



debug(MSG_INFO,


"PUB: topic=%s msg=%s\n"


,topic,message);



ret=1;

out:



blob_buf_init(&b, 0);



blobmsg_add_u8(&b,


"result"


, ret);



ubus_send_reply(ctx, req, b.head);



return


0;

}

/**********************************************************************



* publish method: simple publish messages



*********************************************************************/

static


int


ubus_test_spub(


struct


ubus_context *ctx,


struct


ubus_object *obj,



struct


ubus_request_data *req,


const


char


*method,



struct


blob_attr *msg)

{




int


ret=0;



struct


blob_attr *tb[__UBUS_test_PUB_MAX];



char


*message=


""


, *cmd;



blobmsg_parse(test_pub_policy, __UBUS_test_PUB_MAX, tb, blob_data(msg), blob_len(msg));



if


(!tb[UBUS_test_PUB_TOPIC]){




debug(MSG_ERROR,


"ubus call spub without topic"


);



goto


out;



}



cmd=blobmsg_get_string(tb[UBUS_test_PUB_TOPIC]);



if


(tb[UBUS_test_PUB_MSG]!=NULL){




message=blobmsg_format_json(tb[UBUS_test_PUB_MSG],


true


);



}



simple_pub_msg(cmd, message, 1);



ret=1;

out:



blob_buf_init(&b, 0);



blobmsg_add_u8(&b,


"result"


, ret);



ubus_send_reply(ctx, req, b.head);



return


0;

}

/**********************************************************************



* list method: list current subscribe topic



*********************************************************************/

static


int


ubus_test_list(


struct


ubus_context *ctx,


struct


ubus_object *obj,



struct


ubus_request_data *req,


const


char


*method,



struct


blob_attr *msg)

{




get_topic_list(&b);



ubus_send_reply(ctx, req, b.head);



return


0;

}

/**********************************************************************



* ubus method: ubus_pub_stats



*********************************************************************/

static


int


ubus_pub_stats(


struct


ubus_context *ctx,


struct


ubus_object *obj,



struct


ubus_request_data *req,


const


char


*method,



struct


blob_attr *msg)

{




int


ret = 0;



struct


blob_attr *tb[__UBUS_STATS_MAX];



blobmsg_parse(stats_pub_policy, __UBUS_STATS_MAX, tb, blob_data(msg), blob_len(msg));



if


(tb[UBUS_STATS_OBJS]) {




pub_info(tb[UBUS_STATS_OBJS]);



ret = 1;



}




blob_buf_init(&b, 0);



blobmsg_add_u8(&b,


"result"


, ret);



ubus_send_reply(ctx, req, b.head);




return


0;

}

/**********************************************************************



* list method: list current subscribe topic



*********************************************************************/

static


int


ubus_test_test(


struct


ubus_context *ctx,


struct


ubus_object *obj,



struct


ubus_request_data *req,


const


char


*method,



struct


blob_attr *msg)

{




int


status;



get_topic_list(&b);



debug(MSG_DEBUG,


"==>begin wait status"


);



wait(&status);



debug(MSG_DEBUG,


"==>after wait status:%d"


, status);




ubus_send_reply(ctx, req, b.head);



return


0;

}

/**********************************************************************



* test method



*********************************************************************/

static


const


struct


ubus_method test_methods[] = {




UBUS_METHOD(


"pub"


,ubus_test_pub,test_pub_policy),



UBUS_METHOD(


"spub"


,ubus_test_spub,test_pub_policy),



UBUS_METHOD(


"sub"


,ubus_test_sub,test_sub_policy),



UBUS_METHOD(


"pubstats"


,ubus_pub_stats, stats_pub_policy),



UBUS_METHOD_NOARG(


"lsub"


,ubus_test_list),



UBUS_METHOD_NOARG(


"test"


,ubus_test_test),

};

/**********************************************************************



* test object



*********************************************************************/

static


struct


ubus_object_type test_object_type =



UBUS_OBJECT_TYPE(


"test"


, test_methods);

static


struct


ubus_object test_object = {




.name =


"test"


,



.type = &test_object_type,



.methods = test_methods,



.n_methods = ARRAY_SIZE(test_methods),

};

static


void


ubus_connect_handler(


struct


ubus_context *ctx)

{




ubus_ctx = ctx;



debug(MSG_DEBUG,


"ubus now connected."


);



ubus_add_uloop(ctx);



ubus_add_object(ctx, &test_object);




return


;

}

static


struct


ubus_auto_conn conn;

static


void


receive_ubus_data(


struct


ubus_request *req,


int


type,


struct


blob_attr *msg)

{




struct


blob_attr **ret = (


struct


blob_attr **)req->priv;



*ret = blob_memdup(msg);

}

int


ubus_send(


const


char


*type,


struct


blob_attr *data)

{




if


(!ubus_ctx || !type || !data) {




return


-1;



}



return


ubus_send_event(ubus_ctx, type, data);

}

int


ubus_call(


const


char


*path,


const


char


*method,



struct


blob_attr *data,


struct


blob_attr **ret)

{




uint32_t id;



int


_ret;



if


(ubus_ctx == NULL) {




return


-1;



}



_ret = ubus_lookup_id(ubus_ctx, path, &id);



if


(_ret) {




debug(MSG_ERROR,


"lookup stats id error!"


);



return


-1;



}




return


ubus_invoke(ubus_ctx, id, method, data, receive_ubus_data, ret, 1000);

}

int


ubus_init(


void


)

{




conn.cb = ubus_connect_handler;



ubus_auto_connect(&conn);



return


0;

}

void


ubus_destory()

{




/*



ubus_remove_object(ubus, &main_object);



ubus_free(ubus);



*/

}




本文出自 “

记录点滴收获成长

” 博客,请务必保留此出处

http://gofly.blog.51cto.com/4344767/1685199