luat_lib_ble.c 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256
  1. /*
  2. @module ble
  3. @summary 低功耗蓝牙
  4. @version 1.0
  5. @date 2025.6.21
  6. @usage
  7. -- 本库用于操作BLE对象, 需要搭配bluetooth.init()使用
  8. -- 详细用法请查阅demo
  9. -- 模式解释
  10. -- 从机模式(peripheral), 设备会被扫描到, 并且可以被连接
  11. -- 主机模式(central), 设备会扫描其他设备, 并且可以连接其他设备
  12. -- 广播者模式(ibeacon), 设备会周期性的广播beacon信息, 但不会被扫描到, 也不会连接其他设备
  13. -- 观察者模式(scan), 设备会扫描其他设备, 但不会连接其他设备
  14. -- 从机模式(peripheral)的基本流程(概要描述)
  15. -- 1. 初始化蓝牙框架
  16. -- 2. 创建BLE对象
  17. -- local ble_device = bluetooth_device:ble(ble_event_cb)
  18. -- 3. 创建GATT描述
  19. -- local att_db = {xxx}
  20. -- 4. 创建广播信息
  21. -- ble_device:adv_create(adv_data)
  22. -- 5. 开始广播
  23. -- ble_device:adv_start()
  24. -- 6. 等待连接
  25. -- 7. 在回调函数中处理连接事件, 如接收数据, 发送数据等
  26. -- 主机模式(central)的基本流程(概要描述)
  27. -- TODO
  28. -- 广播者模式(ibeacon)的基本流程(概要描述)
  29. -- TODO
  30. -- 观察者模式(scan)的基本流程(概要描述)
  31. -- 1. 初始化蓝牙框架
  32. -- 2. 创建BLE对象
  33. -- local ble_device = bluetooth_device:ble(ble_event_cb)
  34. -- 3. 开始扫描
  35. -- ble_device:scan_start()
  36. -- 4. 在回调函数中处理扫描事件, 如接收设备信息等
  37. -- 5. 按需停止扫描
  38. -- ble_device:scan_stop()
  39. */
  40. #include "luat_base.h"
  41. #include "luat_mem.h"
  42. #include "luat_rtos.h"
  43. #include "luat_msgbus.h"
  44. #include "luat_ble.h"
  45. #include "luat_bluetooth.h"
  46. #include "luat_log.h"
  47. #define LUAT_LOG_TAG "bt.ble"
  48. #define LUAT_BLE_TYPE "BLE*"
  49. extern int g_bt_ble_ref;
  50. extern int g_ble_lua_cb_ref;
  51. int l_ble_callback(lua_State *L, void *ptr)
  52. {
  53. (void)ptr;
  54. rtos_msg_t *msg = (rtos_msg_t *)lua_topointer(L, -1);
  55. luat_ble_event_t evt = (luat_ble_event_t)msg->arg1;
  56. luat_ble_param_t *param = (luat_ble_param_t *)msg->arg2;
  57. uint8_t tmpbuff[16] = {0};
  58. lua_geti(L, LUA_REGISTRYINDEX, g_ble_lua_cb_ref);
  59. if (lua_isfunction(L, -1)){
  60. lua_geti(L, LUA_REGISTRYINDEX, g_bt_ble_ref);
  61. lua_pushinteger(L, evt);
  62. }else{
  63. LLOGE("用户回调函数不存在");
  64. goto exit;
  65. }
  66. switch (evt){
  67. case LUAT_BLE_EVENT_WRITE:{
  68. luat_ble_write_req_t *write_req = &(param->write_req);
  69. lua_createtable(L, 0, 5);
  70. lua_pushliteral(L, "handle");
  71. lua_pushinteger(L, write_req->handle);
  72. lua_settable(L, -3);
  73. lua_pushliteral(L, "uuid_service");
  74. lua_pushlstring(L, (const char *)write_req->uuid_service.uuid, write_req->uuid_service.uuid_type);
  75. lua_settable(L, -3);
  76. lua_pushliteral(L, "uuid_characteristic");
  77. lua_pushlstring(L, (const char *)write_req->uuid_characteristic.uuid, write_req->uuid_characteristic.uuid_type);
  78. lua_settable(L, -3);
  79. if (write_req->uuid_descriptor.uuid[0] != 0 || write_req->uuid_descriptor.uuid[1] != 0){
  80. lua_pushliteral(L, "uuid_descriptor");
  81. lua_pushlstring(L, (const char *)write_req->uuid_descriptor.uuid, write_req->uuid_descriptor.uuid_type);
  82. lua_settable(L, -3);
  83. }
  84. lua_pushliteral(L, "data");
  85. lua_pushlstring(L, (const char *)write_req->value, write_req->value_len);
  86. lua_settable(L, -3);
  87. lua_call(L, 3, 0);
  88. break;
  89. }
  90. case LUAT_BLE_EVENT_READ:
  91. case LUAT_BLE_EVENT_READ_VALUE:{
  92. luat_ble_read_req_t *read_req = &(param->read_req);
  93. lua_createtable(L, 0, 5);
  94. lua_pushliteral(L, "handle");
  95. lua_pushinteger(L, read_req->handle);
  96. lua_settable(L, -3);
  97. lua_pushliteral(L, "uuid_service");
  98. lua_pushlstring(L, (const char *)read_req->uuid_service.uuid, read_req->uuid_service.uuid_type);
  99. lua_settable(L, -3);
  100. lua_pushliteral(L, "uuid_characteristic");
  101. lua_pushlstring(L, (const char *)read_req->uuid_characteristic.uuid, read_req->uuid_characteristic.uuid_type);
  102. lua_settable(L, -3);
  103. if (read_req->uuid_descriptor.uuid[0] != 0 || read_req->uuid_descriptor.uuid[1] != 0){
  104. lua_pushliteral(L, "uuid_descriptor");
  105. lua_pushlstring(L, (const char *)read_req->uuid_descriptor.uuid, read_req->uuid_descriptor.uuid_type);
  106. lua_settable(L, -3);
  107. }
  108. if (evt == LUAT_BLE_EVENT_READ_VALUE){
  109. lua_pushliteral(L, "data");
  110. lua_pushlstring(L, (const char *)read_req->value, read_req->value_len);
  111. lua_settable(L, -3);
  112. }
  113. lua_call(L, 3, 0);
  114. break;
  115. }case LUAT_BLE_EVENT_SCAN_REPORT:{
  116. luat_ble_adv_req_t *adv_req = &(param->adv_req);
  117. lua_createtable(L, 0, 4);
  118. lua_pushliteral(L, "rssi");
  119. lua_pushinteger(L, adv_req->rssi);
  120. lua_settable(L, -3);
  121. lua_pushliteral(L, "addr_type");
  122. lua_pushinteger(L, adv_req->adv_addr_type);
  123. lua_settable(L, -3);
  124. lua_pushliteral(L, "adv_addr");
  125. lua_pushlstring(L, (const char *)adv_req->adv_addr, 6);
  126. lua_settable(L, -3);
  127. lua_pushliteral(L, "data");
  128. lua_pushlstring(L, (const char *)adv_req->data, adv_req->data_len);
  129. lua_settable(L, -3);
  130. // uint8_t actv_idx; /**< The index of the activity */
  131. // uint8_t evt_type; /**< Event type (see enum \ref adv_report_info and see enum \ref adv_report_type)*/
  132. lua_call(L, 3, 0);
  133. break;
  134. }case LUAT_BLE_EVENT_GATT_ITEM:{
  135. luat_ble_gatt_service_t *gatt_service = param->gatt_item_ind.gatt_service;
  136. lua_newtable(L);
  137. // servise uuid
  138. lua_pushlstring(L, (const char *)gatt_service->uuid, gatt_service->uuid_type);
  139. lua_rawseti(L, -2, 1);
  140. // characteristics
  141. uint8_t characteristics_num = gatt_service->characteristics_num;
  142. for (size_t m = 0; m < characteristics_num; m++){
  143. luat_ble_gatt_chara_t *gatt_chara = &gatt_service->characteristics[m];
  144. lua_newtable(L);
  145. lua_pushlstring(L, (const char *)gatt_chara->uuid, gatt_chara->uuid_type);
  146. lua_seti(L, -2, 1);
  147. // Properties
  148. lua_pushnumber(L, gatt_chara->perm);
  149. lua_seti(L, -2, 2);
  150. lua_seti(L, -2, m + 2);
  151. }
  152. lua_call(L, 3, 0);
  153. break;
  154. }case LUAT_BLE_EVENT_GATT_DONE:{
  155. uint8_t gatt_service_num = param->gatt_done_ind.gatt_service_num;
  156. lua_newtable(L);
  157. lua_pushinteger(L, gatt_service_num);
  158. lua_setfield(L, -2, "service_num");
  159. lua_call(L, 3, 0);
  160. break;
  161. }case LUAT_BLE_EVENT_CONN:{
  162. luat_ble_conn_ind_t *conn = &(param->conn_ind);
  163. lua_newtable(L);
  164. memcpy(tmpbuff, conn->peer_addr, 6);
  165. luat_bluetooth_mac_swap(tmpbuff);
  166. lua_pushlstring(L, (const char *)tmpbuff, 6);
  167. lua_setfield(L, -2, "addr");
  168. lua_pushinteger(L, conn->peer_addr_type);
  169. lua_setfield(L, -2, "addr_type");
  170. lua_call(L, 3, 0);
  171. break;
  172. }case LUAT_BLE_EVENT_DISCONN:{
  173. luat_ble_disconn_ind_t *disconn = &(param->disconn_ind);
  174. lua_newtable(L);
  175. lua_pushinteger(L, disconn->reason);
  176. lua_setfield(L, -2, "reason");
  177. lua_call(L, 3, 0);
  178. break;
  179. }
  180. default:
  181. lua_call(L, 2, 0);
  182. break;
  183. }
  184. exit:
  185. if (param)
  186. {
  187. if (LUAT_BLE_EVENT_WRITE == evt && param->write_req.value_len)
  188. {
  189. // LLOGD("free write_req.value %p", param->write_req.value);
  190. luat_heap_free(param->write_req.value);
  191. param->write_req.value = NULL;
  192. }
  193. else if (LUAT_BLE_EVENT_SCAN_REPORT == evt && param->adv_req.data)
  194. {
  195. // LLOGD("free adv_req.data %p", param->adv_req.data);
  196. luat_heap_free(param->adv_req.data);
  197. param->adv_req.data = NULL;
  198. }
  199. else if (LUAT_BLE_EVENT_READ_VALUE == evt && param->read_req.value_len){
  200. // LLOGD("free read_req.value %p", param->read_req.value);
  201. luat_heap_free(param->read_req.value);
  202. param->read_req.value = NULL;
  203. }
  204. luat_heap_free(param);
  205. param = NULL;
  206. }
  207. return 0;
  208. }
  209. void luat_ble_cb(luat_ble_t *args, luat_ble_event_t ble_event, luat_ble_param_t *ble_param){
  210. // LLOGD("ble event: %d param: %p", ble_event, ble_param);
  211. luat_ble_param_t *luat_ble_param = NULL;
  212. if (ble_param){
  213. // LLOGD("ble param: %p", ble_param);
  214. luat_ble_param = luat_heap_malloc(sizeof(luat_ble_param_t));
  215. memset(luat_ble_param,0,sizeof(luat_ble_param_t));
  216. memcpy(luat_ble_param, ble_param, sizeof(luat_ble_param_t));
  217. if (ble_event == LUAT_BLE_EVENT_WRITE && ble_param->write_req.value_len){
  218. luat_ble_param->write_req.value = luat_heap_malloc(ble_param->write_req.value_len);
  219. memcpy(luat_ble_param->write_req.value, ble_param->write_req.value, ble_param->write_req.value_len);
  220. }else if (ble_event == LUAT_BLE_EVENT_READ_VALUE && ble_param->read_req.value_len){
  221. luat_ble_param->read_req.value = luat_heap_malloc(ble_param->read_req.value_len);
  222. memcpy(luat_ble_param->read_req.value, ble_param->read_req.value, ble_param->read_req.value_len);
  223. }else if (ble_event == LUAT_BLE_EVENT_SCAN_REPORT && ble_param->adv_req.data_len){
  224. luat_ble_param->adv_req.data = luat_heap_malloc(ble_param->adv_req.data_len);
  225. memcpy(luat_ble_param->adv_req.data, ble_param->adv_req.data, ble_param->adv_req.data_len);
  226. }
  227. }
  228. rtos_msg_t msg = {
  229. .handler = l_ble_callback,
  230. .ptr = (void *)NULL,
  231. .arg1 = (int)ble_event,
  232. .arg2 = (int)luat_ble_param,
  233. };
  234. luat_msgbus_put(&msg, 0);
  235. }
  236. /*
  237. 创建一个BLE GATT服务
  238. @api ble.gatt_create(opts)
  239. @table GATT服务的描述信息
  240. @return boolean 是否创建成功
  241. @usage
  242. local att_db = { -- Service
  243. string.fromHex("FA00"), -- Service UUID, 服务的UUID, 可以是16位、32位或128位
  244. -- Characteristic
  245. { -- Characteristic 1
  246. string.fromHex("EA01"), -- Characteristic UUID Value, 特征的UUID值, 可以是16位、32位或128位
  247. ble.NOTIFY | ble.READ | ble.WRITE -- Properties, 对应蓝牙特征的属性, 参考权限常量
  248. string.fromHex("1234"), -- 默认value
  249. }
  250. }
  251. ble_device:gatt_create(att_db)
  252. */
  253. static int l_ble_gatt_create(lua_State *L){
  254. if (!lua_isuserdata(L, 1)){
  255. return 0;
  256. }
  257. uint8_t characteristics_num = 0;
  258. size_t len = 0;
  259. luat_ble_gatt_service_t *luat_ble_gatt_service = luat_heap_malloc(sizeof(luat_ble_gatt_service_t));
  260. memset(luat_ble_gatt_service, 0, sizeof(luat_ble_gatt_service_t));
  261. if (lua_type(L, 2) != LUA_TTABLE){
  262. LLOGE("error param");
  263. return 0;
  264. }
  265. int gatt_table_len = luaL_len(L, 2) - 1;
  266. if (lua_rawgeti(L, -1, 1) == LUA_TSTRING){
  267. const char *service_uuid = luaL_checklstring(L, -1, &len);
  268. if (len == 2){
  269. luat_ble_gatt_service->uuid_type = LUAT_BLE_UUID_TYPE_16;
  270. }else if (len == 4){
  271. luat_ble_gatt_service->uuid_type = LUAT_BLE_UUID_TYPE_32;
  272. }else if (len == 16){
  273. luat_ble_gatt_service->uuid_type = LUAT_BLE_UUID_TYPE_128;
  274. }
  275. memcpy(luat_ble_gatt_service->uuid, service_uuid, len);
  276. }else if (lua_rawgeti(L, -1, 1) == LUA_TNUMBER){
  277. uint16_t service_uuid = (uint16_t)luaL_checknumber(L, -1);
  278. luat_ble_gatt_service->uuid_type = LUAT_BLE_UUID_TYPE_16;
  279. luat_ble_gatt_service->uuid[0] = service_uuid & 0xff;
  280. luat_ble_gatt_service->uuid[1] = service_uuid >> 8;
  281. }else{
  282. LLOGE("error uuid type");
  283. return 0;
  284. }
  285. lua_pop(L, 1);
  286. // Characteristics
  287. luat_ble_gatt_service->characteristics = (luat_ble_gatt_chara_t *)luat_heap_malloc(sizeof(luat_ble_gatt_chara_t) * gatt_table_len);
  288. memset(luat_ble_gatt_service->characteristics, 0, sizeof(luat_ble_gatt_chara_t) * gatt_table_len);
  289. luat_ble_gatt_chara_t *characteristics = luat_ble_gatt_service->characteristics;
  290. for (size_t j = 2; j <= gatt_table_len + 1; j++){
  291. if (lua_rawgeti(L, -1, j) == LUA_TTABLE){
  292. lua_rawgeti(L, -1, 1);
  293. // lua_pushstring(L, "descriptor");
  294. // if (LUA_TSTRING == lua_gettable(L, -2)){
  295. // const char* value = luaL_checklstring(L, -1, &len);
  296. // characteristics[j-2].value = luat_heap_malloc(len);
  297. // characteristics[j-2].value_len = len;
  298. // }
  299. // lua_pop(L, 1);
  300. // UUID
  301. uint16_t uuid_type = 0;
  302. uint8_t uuid[LUAT_BLE_UUID_LEN_MAX] = {0};
  303. if (LUA_TSTRING == lua_type(L, -1)){
  304. const char *characteristics_uuid = luaL_checklstring(L, -1, &len);
  305. uuid_type = len;
  306. memcpy(uuid, characteristics_uuid, len);
  307. }else if (LUA_TNUMBER == lua_type(L, -1)){
  308. uint16_t characteristics_uuid = (uint16_t)luaL_checknumber(L, -1);
  309. uuid_type = LUAT_BLE_UUID_TYPE_16;
  310. uuid[0] = characteristics_uuid >> 8;
  311. uuid[1] = characteristics_uuid & 0xFF;
  312. }else{
  313. LLOGE("error characteristics uuid type");
  314. goto error_exit;
  315. }
  316. lua_pop(L, 1);
  317. if (characteristics[characteristics_num].uuid_type == LUAT_BLE_UUID_TYPE_16 &&
  318. characteristics[characteristics_num].uuid[0] == (LUAT_BLE_GATT_DESC_MAX >> 8) &&
  319. characteristics[characteristics_num].uuid[1] <= (LUAT_BLE_GATT_DESC_MAX & 0xFF)){
  320. // Descriptors
  321. characteristics[characteristics_num].perm |= LUAT_BLE_GATT_PERM_READ;
  322. characteristics[characteristics_num].perm |= LUAT_BLE_GATT_PERM_WRITE;
  323. characteristics[characteristics_num].max_size = 0;
  324. luat_ble_gatt_descriptor_t *descriptor = characteristics[characteristics_num].descriptor;
  325. if (descriptor){
  326. descriptor = luat_heap_realloc(descriptor,sizeof(luat_ble_gatt_descriptor_t)*(characteristics[characteristics_num].descriptors_num+1));
  327. descriptor[characteristics[characteristics_num].descriptors_num].uuid_type = uuid_type;
  328. memcpy(descriptor[characteristics[characteristics_num].descriptors_num].uuid, uuid, len);
  329. }else{
  330. descriptor = luat_heap_malloc(sizeof(luat_ble_gatt_descriptor_t));
  331. descriptor->uuid_type = uuid_type;
  332. memcpy(descriptor->uuid, uuid, len);
  333. }
  334. characteristics[characteristics_num].descriptors_num++;
  335. }else{
  336. // Characteristics uuid
  337. characteristics[characteristics_num].uuid_type = uuid_type;
  338. memcpy(characteristics[characteristics_num].uuid, uuid, len);
  339. // Characteristics properties
  340. lua_rawgeti(L, -1, 2);
  341. if (LUA_TNUMBER == lua_type(L, -1)){
  342. characteristics[characteristics_num].perm = (uint16_t)luaL_optnumber(L, -1, 0);
  343. }
  344. lua_pop(L, 1);
  345. // Descriptors
  346. if (characteristics[characteristics_num].perm & LUAT_BLE_GATT_PERM_NOTIFY){
  347. luat_ble_gatt_chara_t *characteristic = &characteristics[characteristics_num];
  348. if (characteristic->descriptor){
  349. uint8_t descriptor_ind = characteristics[characteristics_num].descriptors_num;
  350. characteristic->descriptor = luat_heap_realloc(characteristic->descriptor,sizeof(luat_ble_gatt_descriptor_t)*(descriptor_ind+1));
  351. memset(&characteristic->descriptor[descriptor_ind],0,sizeof(luat_ble_gatt_descriptor_t));
  352. characteristic->descriptor[descriptor_ind].uuid_type = LUAT_BLE_UUID_TYPE_16;
  353. characteristic->descriptor[descriptor_ind].uuid[0] = 0x2902 >> 8;
  354. characteristic->descriptor[descriptor_ind].uuid[1] = 0x2902 & 0xFF;
  355. }else{
  356. characteristic->descriptor = luat_heap_malloc(sizeof(luat_ble_gatt_descriptor_t));
  357. memset(characteristic->descriptor,0,sizeof(luat_ble_gatt_descriptor_t));
  358. characteristic->descriptor->uuid_type = LUAT_BLE_UUID_TYPE_16;
  359. characteristic->descriptor->uuid[0] = 0x2902 >> 8;
  360. characteristic->descriptor->uuid[1] = 0x2902 & 0xFF;
  361. }
  362. characteristics[characteristics_num].descriptors_num++;
  363. }
  364. // Characteristics value
  365. lua_rawgeti(L, -1, 3);
  366. if (LUA_TSTRING == lua_type(L, -1)){
  367. const char *value = luaL_checklstring(L, -1, &len);
  368. characteristics[characteristics_num].value = luat_heap_malloc(len);
  369. memcpy(characteristics[characteristics_num].value, value, len);
  370. characteristics[characteristics_num].value_len = len;
  371. }
  372. lua_pop(L, 1);
  373. // Characteristics max_size
  374. lua_pushstring(L, "max_size");
  375. if (LUA_TNUMBER == lua_gettable(L, -2)){
  376. characteristics[characteristics_num].max_size = (uint16_t)luaL_optnumber(L, -1, 0);
  377. }else{
  378. characteristics[characteristics_num].max_size = 256;
  379. }
  380. lua_pop(L, 1);
  381. characteristics_num++;
  382. }
  383. }
  384. lua_pop(L, 1);
  385. }
  386. luat_ble_gatt_service->characteristics_num = characteristics_num;
  387. lua_pushboolean(L, luat_ble_create_gatt(NULL, luat_ble_gatt_service) == 0 ? 1 : 0);
  388. return 1;
  389. error_exit:
  390. return 0;
  391. }
  392. /*
  393. 创建一个BLE广播
  394. @api ble.adv_create(opts)
  395. @table 广播的描述信息
  396. @return boolean 是否创建成功
  397. @usage
  398. -- 创建广播信息
  399. ble_device:adv_create({
  400. addr_mode = ble.PUBLIC, -- 广播地址模式, 可选值: ble.PUBLIC, ble.RANDOM, ble.RPA, ble.NRPA
  401. channel_map = ble.CHNLS_ALL, -- 广播的通道, 可选值: ble.CHNLS_37, ble.CHNLS_38, ble.CHNLS_39, ble.CHNLS_ALL
  402. intv_min = 120, -- 广播间隔最小值, 单位为0.625ms, 最小值为20, 最大值为10240
  403. intv_max = 120, -- 广播间隔最大值, 单位为0.625ms, 最小值为20, 最大值为10240
  404. adv_data = { -- 支持表格形式, 也支持字符串形式(255字节以内)
  405. {ble.FLAGS, string.char(0x06)},
  406. {ble.COMPLETE_LOCAL_NAME, "LuatOS123"}, -- 广播的设备名
  407. {ble.SERVICE_DATA, string.fromHex("FE01")}, -- 广播的服务数据
  408. {ble.MANUFACTURER_SPECIFIC_DATA, string.fromHex("05F0")}
  409. }
  410. })
  411. */
  412. static int l_ble_advertising_create(lua_State *L){
  413. if (!lua_isuserdata(L, 1)){
  414. return 0;
  415. }
  416. if (lua_type(L, 2) != LUA_TTABLE){
  417. LLOGE("error param");
  418. return 0;
  419. }
  420. size_t len = 0;
  421. uint8_t local_name_set_flag = 0;
  422. const char complete_local_name[32] = {0};
  423. luat_ble_adv_cfg_t luat_ble_adv_cfg = {
  424. .addr_mode = LUAT_BLE_ADDR_MODE_PUBLIC,
  425. .channel_map = LUAT_BLE_ADV_CHNLS_ALL,
  426. .intv_min = 120,
  427. .intv_max = 160,
  428. .adv_type = LUAT_BLE_ADV_TYPE_LEGACY,
  429. .adv_prop = LUAT_BLE_ADV_PROP_CONNECTABLE | LUAT_BLE_ADV_PROP_SCANNABLE,
  430. };
  431. lua_pushstring(L, "addr_mode");
  432. if (LUA_TNUMBER == lua_gettable(L, -2)){
  433. luat_ble_adv_cfg.addr_mode = luaL_checknumber(L, -1);
  434. }
  435. lua_pop(L, 1);
  436. lua_pushstring(L, "channel_map");
  437. if (LUA_TNUMBER == lua_gettable(L, 2)){
  438. luat_ble_adv_cfg.channel_map = luaL_checknumber(L, -1);
  439. }
  440. lua_pop(L, 1);
  441. lua_pushstring(L, "intv_min");
  442. if (LUA_TNUMBER == lua_gettable(L, 2)){
  443. luat_ble_adv_cfg.intv_min = luaL_checknumber(L, -1);
  444. }
  445. lua_pop(L, 1);
  446. lua_pushstring(L, "intv_max");
  447. if (LUA_TNUMBER == lua_gettable(L, 2)){
  448. luat_ble_adv_cfg.intv_max = luaL_checknumber(L, -1);
  449. }
  450. lua_pop(L, 1);
  451. lua_pushstring(L, "adv_type");
  452. if (LUA_TNUMBER == lua_gettable(L, 2)){
  453. luat_ble_adv_cfg.adv_type = luaL_checknumber(L, -1);
  454. }
  455. lua_pop(L, 1);
  456. lua_pushstring(L, "adv_prop");
  457. if (LUA_TNUMBER == lua_gettable(L, 2)){
  458. luat_ble_adv_cfg.adv_prop = luaL_checknumber(L, -1);
  459. }
  460. lua_pop(L, 1);
  461. luat_ble_create_advertising(NULL, &luat_ble_adv_cfg);
  462. // 广播内容 (adv data)
  463. uint8_t adv_data[255] = {0};
  464. uint8_t adv_index = 0;
  465. lua_pushstring(L, "adv_data");
  466. if (LUA_TTABLE == lua_gettable(L, -2)){
  467. int adv_data_count = luaL_len(L, -1);
  468. for (int i = 1; i <= adv_data_count; i++){
  469. lua_rawgeti(L, -1, i);
  470. if (LUA_TTABLE == lua_type(L, -1)){
  471. lua_rawgeti(L, -1, 2);
  472. if (lua_type(L, -1) == LUA_TSTRING){
  473. const char *data = luaL_checklstring(L, -1, &len);
  474. adv_data[adv_index++] = (uint8_t)(len + 1);
  475. lua_rawgeti(L, -2, 1);
  476. if (lua_type(L, -1) == LUA_TNUMBER){
  477. uint8_t adv_type = (uint8_t)luaL_checknumber(L, -1);
  478. adv_data[adv_index++] = adv_type;
  479. if (adv_type == LUAT_ADV_TYPE_COMPLETE_LOCAL_NAME){
  480. luat_ble_set_name(NULL, data, len);
  481. local_name_set_flag = 1;
  482. }
  483. }else{
  484. LLOGE("error adv_data type");
  485. goto end;
  486. }
  487. memcpy(adv_data + adv_index, data, len);
  488. adv_index += len;
  489. lua_pop(L, 2);
  490. }else{
  491. LLOGE("error adv_data type");
  492. goto end;
  493. }
  494. }else{
  495. LLOGE("error adv_data type");
  496. goto end;
  497. }
  498. lua_pop(L, 1);
  499. }
  500. }
  501. else if (lua_isstring(L, -1)){
  502. // 字符串形式
  503. const char *data = luaL_checklstring(L, -1, &len);
  504. if (len > 255) {
  505. LLOGE("adv_data too long, max length is 255");
  506. goto end;
  507. }
  508. memcpy(adv_data, data, len);
  509. adv_index = len;
  510. }
  511. else {
  512. LLOGE("error adv_data type");
  513. goto end;
  514. }
  515. lua_pop(L, 1);
  516. if (!local_name_set_flag){
  517. sprintf_(complete_local_name, "LuatOS_%s", luat_os_bsp());
  518. luat_ble_set_name(NULL, complete_local_name, strlen(complete_local_name));
  519. }
  520. /* set adv paramters */
  521. luat_ble_set_adv_data(NULL, adv_data, adv_index);
  522. lua_pushstring(L, "rsp_data");
  523. if (LUA_TSTRING == lua_gettable(L, 2)){
  524. uint8_t *rsp_data = luaL_checklstring(L, -1, &len);
  525. if (len){
  526. luat_ble_set_scan_rsp_data(NULL, rsp_data, len);
  527. }
  528. }
  529. lua_pop(L, 1);
  530. lua_pushboolean(L, 1);
  531. return 1;
  532. end:
  533. return 0;
  534. }
  535. /*
  536. 开始广播
  537. @api ble.adv_start()
  538. @return boolean 是否成功
  539. @usage
  540. -- 开始广播
  541. ble_device:adv_start()
  542. -- 提醒, 对于从机模式, 如果被断开了连接, 则需要重新开始广播, 才能被重新搜索到
  543. */
  544. static int l_ble_advertising_start(lua_State *L){
  545. lua_pushboolean(L, luat_ble_start_advertising(NULL) ? 0 : 1);
  546. return 1;
  547. }
  548. /*
  549. 主动停止广播
  550. @api ble.adv_stop()
  551. @return boolean 是否成功
  552. @usage
  553. -- 停止广播
  554. ble_device:adv_stop()
  555. */
  556. static int l_ble_advertising_stop(lua_State *L){
  557. lua_pushboolean(L, luat_ble_stop_advertising(NULL) ? 0 : 1);
  558. return 1;
  559. }
  560. /*
  561. 写入带通知的特征值
  562. @api ble.write_notify(opts, value)
  563. @table 特征值的描述信息
  564. @string value 要写入的值
  565. @return boolean 是否成功
  566. @usage
  567. -- 写入带通知的特征值
  568. ble_device:write_notify({
  569. uuid_service = "FA00", -- 服务的UUID, 可以是16位、32位或128位
  570. uuid_characteristic = "EA01", -- 特征的UUID值, 可以是16位、32位或128位
  571. }, "Hello BLE") -- 要写入的值
  572. */
  573. static int l_ble_write_notify(lua_State *L){
  574. uint16_t ret = 0;
  575. const char *service_uuid = NULL;
  576. const char *characteristic_uuid = NULL;
  577. const char *descriptor_uuid = NULL;
  578. luat_ble_uuid_t service = {0};
  579. luat_ble_uuid_t characteristic = {0};
  580. luat_ble_uuid_t descriptor = {0};
  581. size_t tmp = 0;
  582. if (1){
  583. size_t len = 0;
  584. const char *value = luaL_checklstring(L, 3, &len);
  585. lua_pushstring(L, "uuid_service");
  586. if (LUA_TSTRING == lua_gettable(L, 2)){
  587. service_uuid = luaL_checklstring(L, -1, &tmp);
  588. service.uuid_type = tmp;
  589. memcpy(service.uuid, service_uuid, service.uuid_type);
  590. // LLOGD("uuid_service: %02X %02X", service.uuid[0], service.uuid[1]);
  591. }
  592. else{
  593. LLOGW("缺失 uuid_service 参数");
  594. goto end_error;
  595. }
  596. lua_pop(L, 1);
  597. lua_pushstring(L, "uuid_characteristic");
  598. if (LUA_TSTRING == lua_gettable(L, 2)){
  599. characteristic_uuid = luaL_checklstring(L, -1, &tmp);
  600. characteristic.uuid_type = tmp;
  601. memcpy(characteristic.uuid, characteristic_uuid, characteristic.uuid_type);
  602. // LLOGD("uuid_characteristic: %02X %02X", characteristic.uuid[0], characteristic.uuid[1]);
  603. }
  604. else{
  605. LLOGW("缺失 uuid_characteristic 参数");
  606. goto end_error;
  607. }
  608. lua_pop(L, 1);
  609. lua_pushstring(L, "uuid_descriptor");
  610. if (LUA_TSTRING == lua_gettable(L, 2)){
  611. descriptor_uuid = luaL_checklstring(L, -1, &tmp);
  612. descriptor.uuid_type = tmp;
  613. memcpy(descriptor.uuid, descriptor_uuid, descriptor.uuid_type);
  614. // LLOGD("uuid_descriptor: %02X %02X", descriptor.uuid[0], descriptor.uuid[1]);
  615. ret = luat_ble_write_notify_value(&service, &characteristic, &descriptor, (uint8_t *)value, len);
  616. }else{
  617. ret = luat_ble_write_notify_value(&service, &characteristic, NULL, (uint8_t *)value, len);
  618. }
  619. lua_pop(L, 1);
  620. // LLOGD("luat_ble_write_notify_value ret %d", ret);
  621. lua_pushboolean(L, ret == 0 ? 1 : 0);
  622. return 1;
  623. }
  624. end_error:
  625. LLOGE("error param");
  626. return 0;
  627. }
  628. /*
  629. 写入带指示的特征值
  630. @api ble.write_indicate(opts, value)
  631. @table 特征值的描述信息
  632. @string value 要写入的值
  633. @return boolean 是否成功
  634. @usage
  635. -- 写入带指示的特征值
  636. ble_device:write_indicate({
  637. uuid_service = "FA00", -- 服务的UUID, 可以是16位、32位或128位
  638. uuid_characteristic = "EA01", -- 特征的UUID值, 可以是16位、32位或128位
  639. }, "Hello BLE") -- 要写入的值
  640. */
  641. static int l_ble_write_indicate(lua_State *L){
  642. uint16_t ret = 0;
  643. const char *service_uuid = NULL;
  644. const char *characteristic_uuid = NULL;
  645. const char *descriptor_uuid = NULL;
  646. luat_ble_uuid_t service = {0};
  647. luat_ble_uuid_t characteristic = {0};
  648. luat_ble_uuid_t descriptor = {0};
  649. size_t tmp = 0;
  650. if (1){
  651. size_t len = 0;
  652. const char *value = luaL_checklstring(L, 3, &len);
  653. lua_pushstring(L, "uuid_service");
  654. if (LUA_TSTRING == lua_gettable(L, 2)){
  655. service_uuid = luaL_checklstring(L, -1, &tmp);
  656. service.uuid_type = tmp;
  657. memcpy(service.uuid, service_uuid, service.uuid_type);
  658. // LLOGD("uuid_service: %02X %02X", service.uuid[0], service.uuid[1]);
  659. }
  660. else{
  661. LLOGW("缺失 uuid_service 参数");
  662. goto end_error;
  663. }
  664. lua_pop(L, 1);
  665. lua_pushstring(L, "uuid_characteristic");
  666. if (LUA_TSTRING == lua_gettable(L, 2)){
  667. characteristic_uuid = luaL_checklstring(L, -1, &tmp);
  668. characteristic.uuid_type = tmp;
  669. memcpy(characteristic.uuid, characteristic_uuid, characteristic.uuid_type);
  670. // LLOGD("uuid_characteristic: %02X %02X", characteristic.uuid[0], characteristic.uuid[1]);
  671. }
  672. else{
  673. LLOGW("缺失 uuid_characteristic 参数");
  674. goto end_error;
  675. }
  676. lua_pop(L, 1);
  677. lua_pushstring(L, "uuid_descriptor");
  678. if (LUA_TSTRING == lua_gettable(L, 2)){
  679. descriptor_uuid = luaL_checklstring(L, -1, &tmp);
  680. descriptor.uuid_type = tmp;
  681. memcpy(descriptor.uuid, descriptor_uuid, descriptor.uuid_type);
  682. // LLOGD("uuid_descriptor: %02X %02X", descriptor.uuid[0], descriptor.uuid[1]);
  683. ret = luat_ble_write_indicate_value(&service, &characteristic, &descriptor, (uint8_t *)value, len);
  684. }else{
  685. ret = luat_ble_write_indicate_value(&service, &characteristic, NULL, (uint8_t *)value, len);
  686. }
  687. lua_pop(L, 1);
  688. // LLOGD("luat_ble_write_indicate_value ret %d", ret);
  689. lua_pushboolean(L, ret == 0 ? 1 : 0);
  690. return 1;
  691. }
  692. end_error:
  693. LLOGE("error param");
  694. return 0;
  695. }
  696. /*
  697. 写入特征值
  698. @api ble.write_value(opts, value)
  699. @table 特征值的描述信息
  700. @string value 要写入的值
  701. @return boolean 是否成功
  702. @usage
  703. -- 写入特征值,填充预设值,被动读取
  704. ble_device:write_value({
  705. uuid_service = "FA00", -- 服务的UUID, 可以是16位、32位或128位
  706. uuid_characteristic = "EA01", -- 特征的UUID值, 可以是16位、32位或128位
  707. }, "Hello BLE") -- 要写入的值
  708. */
  709. static int l_ble_write_value(lua_State *L){
  710. uint16_t ret = 0;
  711. const char *service_uuid = NULL;
  712. const char *characteristic_uuid = NULL;
  713. const char *descriptor_uuid = NULL;
  714. luat_ble_uuid_t service = {0};
  715. luat_ble_uuid_t characteristic = {0};
  716. luat_ble_uuid_t descriptor = {0};
  717. size_t tmp = 0;
  718. if (1){
  719. size_t len = 0;
  720. const char *value = luaL_checklstring(L, 3, &len);
  721. lua_pushstring(L, "uuid_service");
  722. if (LUA_TSTRING == lua_gettable(L, 2)){
  723. service_uuid = luaL_checklstring(L, -1, &tmp);
  724. service.uuid_type = tmp;
  725. memcpy(service.uuid, service_uuid, service.uuid_type);
  726. // LLOGD("uuid_service: %02X %02X", service.uuid[0], service.uuid[1]);
  727. }
  728. else{
  729. LLOGW("缺失 uuid_service 参数");
  730. goto end_error;
  731. }
  732. lua_pop(L, 1);
  733. lua_pushstring(L, "uuid_characteristic");
  734. if (LUA_TSTRING == lua_gettable(L, 2)){
  735. characteristic_uuid = luaL_checklstring(L, -1, &tmp);
  736. characteristic.uuid_type = tmp;
  737. memcpy(characteristic.uuid, characteristic_uuid, characteristic.uuid_type);
  738. // LLOGD("uuid_characteristic: %02X %02X", characteristic.uuid[0], characteristic.uuid[1]);
  739. }
  740. else{
  741. LLOGW("缺失 uuid_characteristic 参数");
  742. goto end_error;
  743. }
  744. lua_pop(L, 1);
  745. lua_pushstring(L, "uuid_descriptor");
  746. if (LUA_TSTRING == lua_gettable(L, 2)){
  747. descriptor_uuid = luaL_checklstring(L, -1, &tmp);
  748. descriptor.uuid_type = tmp;
  749. memcpy(descriptor.uuid, descriptor_uuid, descriptor.uuid_type);
  750. // LLOGD("uuid_descriptor: %02X %02X", descriptor.uuid[0], descriptor.uuid[1]);
  751. ret = luat_ble_write_value(&service, &characteristic, &descriptor, (uint8_t *)value, len);
  752. }else{
  753. ret = luat_ble_write_value(&service, &characteristic, NULL, (uint8_t *)value, len);
  754. }
  755. lua_pop(L, 1);
  756. // LLOGD("luat_ble_write_value ret %d", ret);
  757. lua_pushboolean(L, ret == 0 ? 1 : 0);
  758. return 1;
  759. }
  760. end_error:
  761. LLOGE("error param");
  762. return 0;
  763. }
  764. /*
  765. 读取特征值
  766. @api ble.read_value(opts)
  767. @table 特征值的描述信息
  768. @return boolean 是否成功
  769. @usage
  770. -- 读取特征值,通过回调中的 EVENT_READ_VALUE 事件返回读取的value值
  771. ble_device:read_value({
  772. uuid_service = "FA00", -- 服务的UUID, 可以是16位、32位或128位
  773. uuid_characteristic = "EA01", -- 特征的UUID值, 可以是16位、32位或128位
  774. })
  775. */
  776. static int l_ble_read_value(lua_State *L){
  777. uint16_t ret = 0;
  778. const char *service_uuid = NULL;
  779. const char *characteristic_uuid = NULL;
  780. const char *descriptor_uuid = NULL;
  781. luat_ble_uuid_t service = {0};
  782. luat_ble_uuid_t characteristic = {0};
  783. luat_ble_uuid_t descriptor = {0};
  784. size_t tmp = 0;
  785. if (1){
  786. size_t len = 0;
  787. uint8_t* value = NULL;
  788. lua_pushstring(L, "uuid_service");
  789. if (LUA_TSTRING == lua_gettable(L, 2)){
  790. service_uuid = luaL_checklstring(L, -1, &tmp);
  791. service.uuid_type = tmp;
  792. memcpy(service.uuid, service_uuid, service.uuid_type);
  793. // LLOGD("uuid_service: %02X %02X", service.uuid[0], service.uuid[1]);
  794. }
  795. else{
  796. LLOGW("缺失 uuid_service 参数");
  797. goto end_error;
  798. }
  799. lua_pop(L, 1);
  800. lua_pushstring(L, "uuid_characteristic");
  801. if (LUA_TSTRING == lua_gettable(L, 2)){
  802. characteristic_uuid = luaL_checklstring(L, -1, &tmp);
  803. characteristic.uuid_type = tmp;
  804. memcpy(characteristic.uuid, characteristic_uuid, characteristic.uuid_type);
  805. // LLOGD("uuid_characteristic: %02X %02X", characteristic.uuid[0], characteristic.uuid[1]);
  806. }
  807. else{
  808. LLOGW("缺失 uuid_characteristic 参数");
  809. goto end_error;
  810. }
  811. lua_pop(L, 1);
  812. lua_pushstring(L, "uuid_descriptor");
  813. if (LUA_TSTRING == lua_gettable(L, 2)){
  814. descriptor_uuid = luaL_checklstring(L, -1, &tmp);
  815. descriptor.uuid_type = tmp;
  816. memcpy(descriptor.uuid, descriptor_uuid, descriptor.uuid_type);
  817. // LLOGD("uuid_descriptor: %02X %02X", descriptor.uuid[0], descriptor.uuid[1]);
  818. ret = luat_ble_read_value(&service, &characteristic, &descriptor, &value, &len);
  819. }else{
  820. ret = luat_ble_read_value(&service, &characteristic, NULL, &value, &len);
  821. }
  822. lua_pop(L, 1);
  823. if (ret == 0){
  824. lua_pushlstring(L, (const char *)value, len);
  825. return 1;
  826. }else{
  827. LLOGE("ble read value error");
  828. return 0;
  829. }
  830. }
  831. end_error:
  832. LLOGE("error param");
  833. return 0;
  834. }
  835. /*
  836. 开关监听
  837. @api ble.notify_enable(opts, value)
  838. @table 特征值的描述信息
  839. @boolean enable 开/关 可选,默认开
  840. @return boolean 是否成功
  841. @usage
  842. -- 写入特征值,填充预设值,被动读取
  843. ble_device:notify_enable({
  844. uuid_service = "FA00", -- 服务的UUID, 可以是16位、32位或128位
  845. uuid_characteristic = "EA01", -- 特征的UUID值, 可以是16位、32位或128位
  846. }, true) -- 开/关
  847. */
  848. static int l_ble_notify_enable(lua_State *L){
  849. uint16_t ret = 0;
  850. const char *service_uuid = NULL;
  851. const char *characteristic_uuid = NULL;
  852. luat_ble_uuid_t service = {0};
  853. luat_ble_uuid_t characteristic = {0};
  854. size_t tmp = 0;
  855. if (1){
  856. uint8_t enable = 1;
  857. if (lua_isboolean(L, 3)) {
  858. enable = lua_toboolean(L, 3);
  859. }
  860. lua_pushstring(L, "uuid_service");
  861. if (LUA_TSTRING == lua_gettable(L, 2)){
  862. service_uuid = luaL_checklstring(L, -1, &tmp);
  863. service.uuid_type = tmp;
  864. memcpy(service.uuid, service_uuid, service.uuid_type);
  865. // LLOGD("uuid_service: %02X %02X", service.uuid[0], service.uuid[1]);
  866. }
  867. else{
  868. LLOGW("缺失 uuid_service 参数");
  869. goto end_error;
  870. }
  871. lua_pop(L, 1);
  872. lua_pushstring(L, "uuid_characteristic");
  873. if (LUA_TSTRING == lua_gettable(L, 2)){
  874. characteristic_uuid = luaL_checklstring(L, -1, &tmp);
  875. characteristic.uuid_type = tmp;
  876. memcpy(characteristic.uuid, characteristic_uuid, characteristic.uuid_type);
  877. // LLOGD("uuid_characteristic: %02X %02X", characteristic.uuid[0], characteristic.uuid[1]);
  878. }
  879. else{
  880. LLOGW("缺失 uuid_characteristic 参数");
  881. goto end_error;
  882. }
  883. lua_pop(L, 1);
  884. ret = luat_ble_notify_enable(&service, &characteristic, enable);
  885. // LLOGD("luat_ble_write_value ret %d", ret);
  886. lua_pushboolean(L, ret == 0 ? 1 : 0);
  887. return 1;
  888. }
  889. end_error:
  890. LLOGE("error param");
  891. return 0;
  892. }
  893. /*
  894. 创建一个BLE扫描
  895. @api ble.scan_create(addr_mode, scan_interval, scan_window)
  896. @number addr_mode 广播地址模式, 可选值: ble.PUBLIC, ble.RANDOM, ble.RPA, ble.NRPA
  897. @number scan_interval 扫描间隔, 单位为0.625ms, 最小值为20, 最大值为10240
  898. @number scan_window 扫描窗口, 单位为0.625ms, 最小值为20, 最大值为10240
  899. @return boolean 是否创建成功
  900. @usage
  901. -- 创建BLE扫描
  902. ble_device:scan_create(ble.PUBLIC, 100, 100)
  903. */
  904. static int l_ble_scanning_create(lua_State *L){
  905. if (!lua_isuserdata(L, 1)){
  906. return 0;
  907. }
  908. if (1){
  909. luat_ble_scan_cfg_t cfg = {
  910. .addr_mode = LUAT_BLE_ADDR_MODE_PUBLIC,
  911. .scan_interval = 100,
  912. .scan_window = 100,
  913. };
  914. if (lua_isinteger(L, 2))
  915. {
  916. cfg.addr_mode = luaL_checkinteger(L, 2);
  917. }
  918. if (lua_isinteger(L, 3))
  919. {
  920. cfg.scan_interval = luaL_checkinteger(L, 3);
  921. }
  922. if (lua_isinteger(L, 4))
  923. {
  924. cfg.scan_window = luaL_checkinteger(L, 4);
  925. }
  926. lua_pushboolean(L, luat_ble_create_scanning(NULL, &cfg) ? 0 : 1);
  927. return 1;
  928. }
  929. return 0;
  930. }
  931. /*
  932. 开始BLE扫描
  933. @api ble.scan_start()
  934. @return boolean 是否成功
  935. @usage
  936. -- 开始BLE扫描
  937. ble_device:scan_start()
  938. -- 提醒, 扫描会一直进行, 直到调用ble.scan_stop()停止扫描
  939. -- 扫描结果会立即执行回调, 同一个设备不会去重, 扫描到数据就会执行回调
  940. */
  941. static int l_ble_scanning_start(lua_State *L){
  942. lua_pushboolean(L, luat_ble_start_scanning(NULL) ? 0 : 1);
  943. return 1;
  944. }
  945. /*
  946. 停止BLE扫描
  947. @api ble.scan_stop()
  948. @return boolean 是否成功
  949. @usage
  950. -- 停止BLE扫描
  951. ble_device:scan_stop()
  952. -- 提醒, 扫描会一直进行, 直到调用ble.scan_stop()停止扫描
  953. */
  954. static int l_ble_scanning_stop(lua_State *L){
  955. lua_pushboolean(L, luat_ble_stop_scanning(NULL) ? 0 : 1);
  956. return 1;
  957. }
  958. /*
  959. BLE连接
  960. @api ble.connect()
  961. @string mac 地址
  962. @int 地址类型 ble.PUBLIC ble.RANDOM
  963. @return boolean 是否成功
  964. @usage
  965. -- BLE连接
  966. ble_device:connect(string.fromHex("C8478C4E027D"),0)
  967. */
  968. static int l_ble_connect(lua_State *L){
  969. size_t len = 0;
  970. luat_ble_connect_req_t conn = {0};
  971. uint8_t *adv_addr = luaL_checklstring(L, 2, &len);
  972. uint8_t adv_addr_type = luaL_checknumber(L, 3);
  973. if (len != 6){
  974. LLOGE("error adv_addr len %d", len);
  975. return 0;
  976. }
  977. memcpy(conn.adv_addr, adv_addr, len);
  978. conn.adv_addr_type = adv_addr_type;
  979. // LLOGD(" adv_addr_type:%d, adv_addr:%02x:%02x:%02x:%02x:%02x:%02x",
  980. // adv_addr_type, adv_addr[0], adv_addr[1], adv_addr[2],
  981. // adv_addr[3], adv_addr[4], adv_addr[5]);
  982. lua_pushboolean(L, luat_ble_connect(NULL, &conn) ? 0 : 1);
  983. return 1;
  984. }
  985. /*
  986. BLE断开连接
  987. @api ble.disconnect()
  988. @return boolean 是否成功
  989. @usage
  990. -- BLE断开连接
  991. ble_device:disconnect()
  992. */
  993. static int l_ble_disconnect(lua_State *L){
  994. lua_pushboolean(L, luat_ble_disconnect(NULL) ? 0 : 1);
  995. return 1;
  996. }
  997. /*
  998. 解码广播数据
  999. @api ble.adv_decode(data)
  1000. @string data 广播数据
  1001. @return table 广播数据的解码结果
  1002. @usage
  1003. -- 解码广播数据
  1004. local data = string.fromHex("1EFF060001092002BE0F0AAD8A6D2E251ED6DFBB3D15249929E10BE138DF7B")
  1005. -- 解析广播数据
  1006. local adv_data = ble_device:adv_decode(data)
  1007. if adv_data then
  1008. for k, v in pairs(adv_data) do
  1009. log.info("ble", "adv data", v.len, v.tp, v.data:toHex())
  1010. end
  1011. end
  1012. */
  1013. static int l_ble_adv_decode(lua_State *L) {
  1014. size_t len = 0;
  1015. const char *data = luaL_checklstring(L, 2, &len);
  1016. if (len == 0) {
  1017. lua_pushnil(L);
  1018. return 1;
  1019. }
  1020. lua_newtable(L);
  1021. uint8_t *p = (uint8_t *)data;
  1022. size_t offset = 0;
  1023. int index = 1;
  1024. while (offset < len) {
  1025. uint8_t length = p[offset++];
  1026. if (length == 0 || offset + length > len) {
  1027. LLOGE("Invalid BLE advertisement data");
  1028. lua_pushnil(L);
  1029. return 1;
  1030. }
  1031. uint8_t type = p[offset++];
  1032. lua_newtable(L);
  1033. lua_pushinteger(L, length - 1); // Length does not include the length byte itself
  1034. lua_setfield(L, -2, "len");
  1035. lua_pushinteger(L, type);
  1036. lua_setfield(L, -2, "tp");
  1037. lua_pushlstring(L, (const char *)&p[offset], length - 1); // Data does not include the length byte
  1038. lua_setfield(L, -2, "data");
  1039. lua_seti(L, -2, index);
  1040. offset += length - 1;
  1041. index ++;
  1042. }
  1043. return 1;
  1044. }
  1045. static int _ble_struct_newindex(lua_State *L);
  1046. void luat_ble_struct_init(lua_State *L){
  1047. luaL_newmetatable(L, LUAT_BLE_TYPE);
  1048. lua_pushcfunction(L, _ble_struct_newindex);
  1049. lua_setfield(L, -2, "__index");
  1050. lua_pop(L, 1);
  1051. }
  1052. #include "rotable2.h"
  1053. static const rotable_Reg_t reg_ble[] = {
  1054. // advertise
  1055. {"adv_create", ROREG_FUNC(l_ble_advertising_create)},
  1056. {"adv_start", ROREG_FUNC(l_ble_advertising_start)},
  1057. {"adv_stop", ROREG_FUNC(l_ble_advertising_stop)},
  1058. {"adv_decode", ROREG_FUNC(l_ble_adv_decode)},
  1059. // gatt
  1060. // slaver
  1061. {"gatt_create", ROREG_FUNC(l_ble_gatt_create)},
  1062. {"write_notify", ROREG_FUNC(l_ble_write_notify)},
  1063. {"write_indicate", ROREG_FUNC(l_ble_write_indicate)},
  1064. {"write_value", ROREG_FUNC(l_ble_write_value)},
  1065. {"read_value", ROREG_FUNC(l_ble_read_value)},
  1066. {"notify_enable", ROREG_FUNC(l_ble_notify_enable)},
  1067. // scanning
  1068. {"scan_create", ROREG_FUNC(l_ble_scanning_create)},
  1069. {"scan_start", ROREG_FUNC(l_ble_scanning_start)},
  1070. {"scan_stop", ROREG_FUNC(l_ble_scanning_stop)},
  1071. {"connect", ROREG_FUNC(l_ble_connect)},
  1072. {"disconnect", ROREG_FUNC(l_ble_disconnect)},
  1073. // BLE_EVENT
  1074. {"EVENT_NONE", ROREG_INT(LUAT_BLE_EVENT_NONE)},
  1075. {"EVENT_INIT", ROREG_INT(LUAT_BLE_EVENT_INIT)},
  1076. {"EVENT_DEINIT", ROREG_INT(LUAT_BLE_EVENT_DEINIT)},
  1077. {"EVENT_ADV_INIT", ROREG_INT(LUAT_BLE_EVENT_ADV_INIT)},
  1078. {"EVENT_ADV_START", ROREG_INT(LUAT_BLE_EVENT_ADV_START)},
  1079. {"EVENT_ADV_STOP", ROREG_INT(LUAT_BLE_EVENT_ADV_STOP)},
  1080. {"EVENT_ADV_DEINIT", ROREG_INT(LUAT_BLE_EVENT_ADV_DEINIT)},
  1081. {"EVENT_SCAN_INIT", ROREG_INT(LUAT_BLE_EVENT_SCAN_INIT)},
  1082. {"EVENT_SCAN_START", ROREG_INT(LUAT_BLE_EVENT_SCAN_START)},
  1083. {"EVENT_SCAN_STOP", ROREG_INT(LUAT_BLE_EVENT_SCAN_STOP)},
  1084. {"EVENT_SCAN_DEINIT", ROREG_INT(LUAT_BLE_EVENT_SCAN_DEINIT)},
  1085. {"EVENT_SCAN_REPORT", ROREG_INT(LUAT_BLE_EVENT_SCAN_REPORT)},
  1086. {"EVENT_CONN", ROREG_INT(LUAT_BLE_EVENT_CONN)},
  1087. {"EVENT_DISCONN", ROREG_INT(LUAT_BLE_EVENT_DISCONN)},
  1088. {"EVENT_WRITE", ROREG_INT(LUAT_BLE_EVENT_WRITE)},
  1089. {"EVENT_READ", ROREG_INT(LUAT_BLE_EVENT_READ)},
  1090. {"EVENT_READ_VALUE", ROREG_INT(LUAT_BLE_EVENT_READ_VALUE)},
  1091. {"EVENT_GATT_DONE", ROREG_INT(LUAT_BLE_EVENT_GATT_DONE)},
  1092. {"EVENT_GATT_ITEM", ROREG_INT(LUAT_BLE_EVENT_GATT_ITEM)},
  1093. // ADV_ADDR_MODE
  1094. //@const PUBLIC 控制器的公共地址
  1095. {"PUBLIC", ROREG_INT(LUAT_BLE_ADDR_MODE_PUBLIC)},
  1096. //@const RANDOM 生成的静态地址
  1097. {"RANDOM", ROREG_INT(LUAT_BLE_ADDR_MODE_RANDOM)},
  1098. {"RPA", ROREG_INT(LUAT_BLE_ADDR_MODE_RPA)},
  1099. {"NRPA", ROREG_INT(LUAT_BLE_ADDR_MODE_NRPA)},
  1100. // ADV_CHNL
  1101. //@const CHNL_37 37通道
  1102. {"CHNL_37", ROREG_INT(LUAT_BLE_ADV_CHNL_37)},
  1103. //@const CHNL_38 38通道
  1104. {"CHNL_38", ROREG_INT(LUAT_BLE_ADV_CHNL_38)},
  1105. //@const CHNL_39 39通道
  1106. {"CHNL_39", ROREG_INT(LUAT_BLE_ADV_CHNL_39)},
  1107. //@const CHNLS_ALL 所有通道(37 38 39)
  1108. {"CHNLS_ALL", ROREG_INT(LUAT_BLE_ADV_CHNLS_ALL)},
  1109. // Permission
  1110. //@const READ 读权限
  1111. {"READ", ROREG_INT(LUAT_BLE_GATT_PERM_READ)},
  1112. //@const WRITE 写权限
  1113. {"WRITE", ROREG_INT(LUAT_BLE_GATT_PERM_WRITE)},
  1114. //@const IND 指示权限
  1115. {"IND", ROREG_INT(LUAT_BLE_GATT_PERM_IND)},
  1116. //@const NOTIFY 通知权限
  1117. {"NOTIFY", ROREG_INT(LUAT_BLE_GATT_PERM_NOTIFY)},
  1118. //@const WRITE_CMD 写权限(无需确认)
  1119. {"WRITE_CMD", ROREG_INT(LUAT_BLE_GATT_PERM_WRITE_CMD)},
  1120. // FLAGS
  1121. {"FLAGS", ROREG_INT(LUAT_ADV_TYPE_FLAGS)},
  1122. {"COMPLETE_LOCAL_NAME", ROREG_INT(LUAT_ADV_TYPE_COMPLETE_LOCAL_NAME)},
  1123. {"SERVICE_DATA", ROREG_INT(LUAT_ADV_TYPE_SERVICE_DATA_16BIT)},
  1124. {"MANUFACTURER_SPECIFIC_DATA", ROREG_INT(LUAT_ADV_TYPE_MANUFACTURER_SPECIFIC_DATA)},
  1125. // adv type
  1126. {"ADV_TYPE_LEGACY", ROREG_INT(LUAT_BLE_ADV_TYPE_LEGACY)},
  1127. {"ADV_TYPE_EXTENDED", ROREG_INT(LUAT_BLE_ADV_TYPE_EXTENDED)},
  1128. {"ADV_TYPE_SCAN_RESPONSE", ROREG_INT(LUAT_BLE_ADV_PERIODIC)},
  1129. // adv prop
  1130. {"ADV_PROP_CONNECTABLE", ROREG_INT(LUAT_BLE_ADV_PROP_CONNECTABLE)},
  1131. {"ADV_PROP_SCANNABLE", ROREG_INT(LUAT_BLE_ADV_PROP_SCANNABLE)},
  1132. {"ADV_PROP_DIRECTED", ROREG_INT(LUAT_BLE_ADV_PROP_DIRECTED)},
  1133. {"ADV_PROP_HDC", ROREG_INT(LUAT_BLE_ADV_PROP_HDC)},
  1134. {"ADV_PROP_ANONYMOUS", ROREG_INT(LUAT_BLE_ADV_PROP_ANONYMOUS)},
  1135. {"ADV_PROP_LEGACY", ROREG_INT(LUAT_BLE_ADV_PROP_LEGACY)},
  1136. {"ADV_PROP_TX_PWR", ROREG_INT(LUAT_BLE_ADV_PROP_TX_PWR)},
  1137. {NULL, ROREG_INT(0)}};
  1138. static int _ble_struct_newindex(lua_State *L){
  1139. const rotable_Reg_t *reg = reg_ble;
  1140. const char *key = luaL_checkstring(L, 2);
  1141. while (1){
  1142. if (reg->name == NULL)
  1143. return 0;
  1144. if (!strcmp(reg->name, key)){
  1145. lua_pushcfunction(L, reg->value.value.func);
  1146. return 1;
  1147. }
  1148. reg++;
  1149. }
  1150. }
  1151. LUAMOD_API int luaopen_ble(lua_State *L){
  1152. rotable2_newlib(L, reg_ble);
  1153. luat_ble_struct_init(L);
  1154. return 1;
  1155. }