luat_lib_airtalk.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. @module airtalk
  3. @summary 设备之间,设备与PC、手机,对讲处理
  4. @catalog 综合应用API
  5. @version 1.0
  6. @date 2025.07.1
  7. @demo airtalk
  8. @tag LUAT_USE_AIRTALK
  9. @usage
  10. -- 本库仅部分BSP支持
  11. -- 主要是 Air8000 和 Air780EXX 系列
  12. -- 详细用法请参考demo
  13. */
  14. #include "luat_base.h"
  15. #include "libemqtt.h"
  16. #include "luat_airtalk.h"
  17. #include "luat_malloc.h"
  18. #include "luat_mqtt.h"
  19. #include "luat_audio.h"
  20. #include "airtalk_api.h"
  21. #define LUAT_LOG_TAG "airtalk"
  22. #include "luat_log.h"
  23. #include "rotable.h"
  24. #define LUAT_MQTT_CTRL_TYPE "MQTTCTRL*"
  25. static int l_airtalk_cb;
  26. static int l_airtalk_handler(lua_State *L, void* ptr) {
  27. (void)ptr;
  28. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  29. lua_pop(L, 1);
  30. if (l_airtalk_cb) {
  31. lua_geti(L, LUA_REGISTRYINDEX, l_airtalk_cb);
  32. if (lua_isfunction(L, -1)) {
  33. lua_pushinteger(L, msg->arg1);
  34. lua_pushinteger(L, msg->arg2);
  35. lua_call(L, 2, 0);
  36. }
  37. }
  38. // 给rtos.recv方法返回个空数据
  39. lua_pushinteger(L, 0);
  40. return 1;
  41. }
  42. /*
  43. 配置airtalk参数
  44. @api airtalk.config(protocol,netc,cache_time,encode_cnt,decode_cnt,audio_pm_mode_when_stop)
  45. @int 语音数据传输协议类型,见airtalk.PROTOCOL_XXX
  46. @userdata network_ctrl或者mqtt客户端,如果协议是mqtt类型,传入mqtt.create返回值,如果是其他类型,传入socket.create的返回值
  47. @int 缓冲时间,单位ms,默认500ms,值越小,delay越小,抗网络波动能力越差
  48. @int 单次编码帧数,默认值5,不能低于2,不能高于5
  49. @int 单次解码帧数,如果缓冲没有足够的帧数,自动补0,默认值5,不能低于2,不能高于10,不能低于encode_cnt, decode_cnt * 4 必须是 encode_cnt的整数倍
  50. @int 对讲停止后,audio的pm状态,默认是audio.SHUTDOWN
  51. @return nil
  52. @usage
  53. mqttc = mqtt.create(nil,"120.55.137.106", 1884)
  54. airtalk.config(airtalk.PROTOCOL_MQTT, mqttc)
  55. */
  56. static int l_airtalk_config(lua_State *L)
  57. {
  58. int airtalk_protocol = luaL_optinteger(L, 1, LUAT_AIRTALK_PROTOCOL_MQTT);
  59. int cache_time = luaL_optinteger(L, 3, 500);
  60. int encode_cnt = luaL_optinteger(L, 4, 5);
  61. int decode_cnt = luaL_optinteger(L, 5, 5);
  62. int audio_pm_mode_when_stop = luaL_optinteger(L, 6, LUAT_AUDIO_PM_SHUTDOWN);
  63. luat_mqtt_ctrl_t * mqtt_ctrl;
  64. switch (airtalk_protocol)
  65. {
  66. case LUAT_AIRTALK_PROTOCOL_MQTT:
  67. if (luaL_testudata(L, 2, LUAT_MQTT_CTRL_TYPE)){
  68. mqtt_ctrl = ((luat_mqtt_ctrl_t *)luaL_checkudata(L, 2, LUAT_MQTT_CTRL_TYPE));
  69. }else{
  70. mqtt_ctrl = ((luat_mqtt_ctrl_t *)lua_touserdata(L, 2));
  71. }
  72. if (!mqtt_ctrl)
  73. {
  74. LLOGE("protocol %d no mqttc", airtalk_protocol);
  75. return 0;
  76. }
  77. luat_airtalk_net_param_config(airtalk_protocol, cache_time);
  78. luat_airtalk_net_set_mqtt_ctrl(mqtt_ctrl);
  79. luat_airtalk_speech_audio_param_config(0, audio_pm_mode_when_stop);
  80. luat_airtalk_speech_set_one_block_frame_cnt(decode_cnt, encode_cnt);
  81. luat_airtalk_net_mqtt_init();
  82. break;
  83. default:
  84. LLOGE("protocol %d no support!", airtalk_protocol);
  85. break;
  86. }
  87. return 0;
  88. }
  89. /*
  90. 注册airtalk事件回调
  91. @api airtalk.on(func)
  92. @function 回调方法
  93. @return nil 无返回值
  94. @usage
  95. airtalk.on(function(event, param)
  96. log.info("airtalk event", event, param)
  97. end)
  98. */
  99. static int l_airtalk_on(lua_State *L) {
  100. if (l_airtalk_cb)
  101. {
  102. luaL_unref(L, LUA_REGISTRYINDEX, l_airtalk_cb);
  103. l_airtalk_cb = 0;
  104. }
  105. if (lua_isfunction(L, 1)) {
  106. lua_pushvalue(L, 1);
  107. l_airtalk_cb = luaL_ref(L, LUA_REGISTRYINDEX);
  108. }
  109. return 0;
  110. }
  111. /*
  112. airtalk启动
  113. @api airtalk.start()
  114. @return nil
  115. @usage
  116. mqttc = mqtt.create(nil,"120.55.137.106", 1884)
  117. airtalk.config(airtalk.PROTOCOL_MQTT, mqttc)
  118. airtalk.on(function(event, param)
  119. log.info("airtalk event", event, param)
  120. end)
  121. airtalk.start()
  122. */
  123. static int l_airtalk_start(lua_State *L)
  124. {
  125. luat_airtalk_speech_init();
  126. luat_airtalk_net_init();
  127. return 0;
  128. }
  129. /*
  130. 配置airtalk RTP协议中的SSRC
  131. @api airtalk.set_ssrc(ssrc)
  132. @int/string ssrc,可以是int也是可以8字节string
  133. @return nil
  134. @usage
  135. */
  136. static int l_airtalk_set_ssrc(lua_State *L)
  137. {
  138. if (lua_isstring(L, 1))
  139. {
  140. size_t len;
  141. const char *id = lua_tolstring(L, 1, &len);//取出字符串数据;
  142. uint32_t ssrc = strtol(id, NULL, 16);
  143. luat_airtalk_net_set_ssrc(ssrc);
  144. }
  145. else
  146. {
  147. luat_airtalk_net_set_ssrc(lua_tointeger(L, 1));
  148. }
  149. return 0;
  150. }
  151. /*
  152. 配置airtalk mqtt类型语音数据的专用topic
  153. @api airtalk.set_topic(topic)
  154. @string topic
  155. @return nil
  156. @usage
  157. airtalk.set_topic("xxxxxxxxxx")
  158. */
  159. static int l_airtalk_set_mqtt_topic(lua_State *L)
  160. {
  161. size_t len;
  162. const char *id = lua_tolstring(L, 1, &len);//取出字符串数据;
  163. luat_airtalk_net_set_mqtt_topic(id, len + 1);
  164. return 0;
  165. }
  166. /*
  167. airtalk对讲工作启动/停止
  168. @api airtalk.speech(on_off, mode, sample)
  169. @boolean 启停控制,true开始,false停止
  170. @int 工作模式,见airtalk.MODE_XXX
  171. @int 音频采样率,目前只有8000和16000,默认16000
  172. @return nil
  173. @usage
  174. --1对1对讲开始
  175. airtalk.speech(true,airtalk.MODE_PERSON,16000)
  176. --1对多对讲开始
  177. airtalk.speech(true,airtalk.MODE_GROUP,16000)
  178. --对讲停止
  179. airtalk.speech(false)
  180. */
  181. static int l_airtalk_speech(lua_State *L)
  182. {
  183. int mode = luaL_optinteger(L, 2, LUAT_AIRTALK_SPEECH_MODE_PERSON);
  184. int sample = luaL_optinteger(L, 3, 16000);
  185. int on_off = lua_toboolean(L, 1);
  186. if (on_off)
  187. {
  188. switch(mode)
  189. {
  190. case LUAT_AIRTALK_SPEECH_MODE_PERSON:
  191. luat_airtalk_use_16k(sample == 16000);
  192. luat_airtalk_net_transfer_start(mode);
  193. luat_airtalk_speech_record_switch(1);
  194. break;
  195. case LUAT_AIRTALK_SPEECH_MODE_GROUP:
  196. luat_airtalk_use_16k(sample == 16000);
  197. luat_airtalk_net_transfer_start(mode);
  198. break;
  199. }
  200. }
  201. else
  202. {
  203. luat_airtalk_net_transfer_stop();
  204. luat_airtalk_speech_record_switch(0);
  205. }
  206. return 0;
  207. }
  208. /*
  209. airtalk上行控制
  210. @api airtalk.uplink(on_off)
  211. @boolean 录音上行控制,true开始,false停止
  212. @return nil
  213. @usage
  214. --开始录音
  215. airtalk.uplink(true)
  216. --停止录音
  217. airtalk.uplink(false)
  218. */
  219. static int l_airtalk_uplink(lua_State *L)
  220. {
  221. luat_airtalk_speech_record_switch(lua_toboolean(L, 1));
  222. return 0;
  223. }
  224. /*
  225. airtalk的详细调试信息开关
  226. @api airtalk.debug(on_off)
  227. @boolean 调试信息开关,true打开,false关闭
  228. @return nil
  229. */
  230. static int l_airtalk_debug(lua_State *L)
  231. {
  232. uint8_t on_off = lua_toboolean(L, 1);
  233. luat_airtalk_net_debug_switch(on_off);
  234. luat_airtalk_speech_debug_switch(on_off);
  235. return 0;
  236. }
  237. #include "rotable2.h"
  238. static const rotable_Reg_t reg_airtalk[] =
  239. {
  240. { "speech", ROREG_FUNC(l_airtalk_speech)},
  241. { "config", ROREG_FUNC(l_airtalk_config)},
  242. { "on", ROREG_FUNC(l_airtalk_on)},
  243. { "start", ROREG_FUNC(l_airtalk_start)},
  244. { "set_ssrc", ROREG_FUNC(l_airtalk_set_ssrc)},
  245. { "set_topic", ROREG_FUNC(l_airtalk_set_mqtt_topic)},
  246. { "uplink", ROREG_FUNC(l_airtalk_uplink)},
  247. { "debug", ROREG_FUNC(l_airtalk_debug)},
  248. //@const PROTOCOL_MQTT number 语音数据用MQTT传输
  249. { "PROTOCOL_MQTT", ROREG_INT(LUAT_AIRTALK_PROTOCOL_MQTT)},
  250. //@const MODE_PERSON number 对讲工作模式1对1
  251. { "MODE_PERSON", ROREG_INT(LUAT_AIRTALK_SPEECH_MODE_PERSON)},
  252. //@const MODE_GROUP number 对讲工作模式多人
  253. { "MODE_GROUP", ROREG_INT(LUAT_AIRTALK_SPEECH_MODE_GROUP)},
  254. //@const EVENT_OFF_LINE number airtalk离线
  255. { "EVENT_OFF_LINE", ROREG_INT(LUAT_AIRTALK_CB_ON_LINE_IDLE)},
  256. //@const EVENT_ON_LINE_IDLE number airtalk在线处于空闲状态
  257. { "EVENT_ON_LINE_IDLE", ROREG_INT(LUAT_AIRTALK_CB_ON_LINE_IDLE)},
  258. //@const EVENT_PLAY_START number airtalk下行播放开始
  259. { "EVENT_PLAY_START", ROREG_INT(LUAT_AIRTALK_CB_PLAY_START)},
  260. //@const EVENT_PLAY_END number airtalk下行播放结束
  261. { "EVENT_PLAY_END", ROREG_INT(LUAT_AIRTALK_CB_PLAY_END)},
  262. //@const EVENT_RECORD_START number airtalk录音上行开始
  263. { "EVENT_RECORD_START", ROREG_INT(LUAT_AIRTALK_CB_RECORD_START)},
  264. //@const EVENT_RECORD_END number airtalk录音上行结束
  265. { "EVENT_RECORD_END", ROREG_INT(LUAT_AIRTALK_CB_RECORD_END)},
  266. //@const EVENT_AUDIO_START number airtalk audio启动,只要上行和下行有一个开始就启动
  267. { "EVENT_AUDIO_START", ROREG_INT(LUAT_AIRTALK_CB_AUDIO_START)},
  268. //@const EVENT_AUDIO_END number airtalk audio停止,上行和下行都结束才停止
  269. { "EVENT_AUDIO_END", ROREG_INT(LUAT_AIRTALK_CB_AUDIO_END)},
  270. //@const EVENT_ERROR number airtalk发生异常,后续param为异常值
  271. { "EVENT_ERROR", ROREG_INT(LUAT_AIRTALK_CB_ERROR)},
  272. { NULL, ROREG_INT(0) }
  273. };
  274. LUAMOD_API int luaopen_airtalk(lua_State *L)
  275. {
  276. luat_newlib2(L, reg_airtalk);
  277. return 1;
  278. }
  279. LUAT_WEAK void luat_airtalk_callback(uint32_t event, void *param, uint32_t param_len)
  280. {
  281. rtos_msg_t msg = {0};
  282. msg.handler = l_airtalk_handler;
  283. msg.ptr = param;
  284. msg.arg1 = event;
  285. msg.arg2 = param_len;
  286. luat_msgbus_put(&msg, 0);
  287. }