luat_lib_airtalk.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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. break;
  82. default:
  83. LLOGE("protocol %d no support!", airtalk_protocol);
  84. break;
  85. }
  86. return 0;
  87. }
  88. /*
  89. 注册airtalk事件回调
  90. @api airtalk.on(func)
  91. @function 回调方法
  92. @return nil 无返回值
  93. @usage
  94. airtalk.on(function(event, param)
  95. log.info("airtalk event", event, param)
  96. end)
  97. */
  98. static int l_airtalk_on(lua_State *L) {
  99. if (l_airtalk_cb)
  100. {
  101. luaL_unref(L, LUA_REGISTRYINDEX, l_airtalk_cb);
  102. l_airtalk_cb = 0;
  103. }
  104. if (lua_isfunction(L, 1)) {
  105. lua_pushvalue(L, 1);
  106. l_airtalk_cb = luaL_ref(L, LUA_REGISTRYINDEX);
  107. }
  108. return 0;
  109. }
  110. /*
  111. airtalk启动
  112. @api airtalk.start()
  113. @return nil
  114. @usage
  115. mqttc = mqtt.create(nil,"120.55.137.106", 1884)
  116. airtalk.config(airtalk.PROTOCOL_MQTT, mqttc)
  117. airtalk.on(function(event, param)
  118. log.info("airtalk event", event, param)
  119. end)
  120. airtalk.start()
  121. */
  122. static int l_airtalk_start(lua_State *L)
  123. {
  124. luat_airtalk_speech_init();
  125. luat_airtalk_net_init();
  126. return 0;
  127. }
  128. /*
  129. 配置airtalk RTP协议中的SSRC
  130. @api airtalk.set_ssrc(ssrc)
  131. @int/string ssrc,可以是int也是可以8字节string
  132. @return nil
  133. @usage
  134. */
  135. static int l_airtalk_set_ssrc(lua_State *L)
  136. {
  137. if (lua_isstring(L, 1))
  138. {
  139. size_t len;
  140. const char *id = lua_tolstring(L, 1, &len);//取出字符串数据;
  141. uint32_t ssrc = strtol(id, NULL, 16);
  142. luat_airtalk_net_set_ssrc(ssrc);
  143. }
  144. else
  145. {
  146. luat_airtalk_net_set_ssrc(lua_tointeger(L, 1));
  147. }
  148. return 0;
  149. }
  150. /*
  151. 配置airtalk mqtt类型语音数据的专用topic
  152. @api airtalk.set_topic(topic)
  153. @string topic
  154. @return nil
  155. @usage
  156. airtalk.set_topic("xxxxxxxxxx")
  157. */
  158. static int l_airtalk_set_mqtt_topic(lua_State *L)
  159. {
  160. size_t len;
  161. const char *id = lua_tolstring(L, 1, &len);//取出字符串数据;
  162. luat_airtalk_net_set_mqtt_topic(id, len + 1);
  163. return 0;
  164. }
  165. /*
  166. airtalk对讲工作启动/停止
  167. @api airtalk.speech(on_off, mode, sample)
  168. @boolean 启停控制,true开始,false停止
  169. @int 工作模式,见airtalk.MODE_XXX
  170. @int 音频采样率,目前只有8000和16000,默认16000
  171. @return nil
  172. @usage
  173. --1对1对讲开始
  174. airtalk.speech(true,airtalk.MODE_PERSON,16000)
  175. --作为发起方,进行1对多对讲
  176. airtalk.speech(true,airtalk.MODE_GROUP_SPEAKER,16000)
  177. --作为接收方,进行1对多对讲
  178. airtalk.speech(true,airtalk.MODE_GROUP_LISTENER,16000)
  179. --对讲停止
  180. airtalk.speech(false)
  181. */
  182. static int l_airtalk_speech(lua_State *L)
  183. {
  184. int mode = luaL_optinteger(L, 2, LUAT_AIRTALK_SPEECH_MODE_PERSON);
  185. int sample = luaL_optinteger(L, 3, 16000);
  186. int on_off = lua_toboolean(L, 1);
  187. if (on_off)
  188. {
  189. switch(mode)
  190. {
  191. case LUAT_AIRTALK_SPEECH_MODE_PERSON:
  192. luat_airtalk_use_16k(sample == 16000);
  193. //luat_airtalk_speech_start_play(sample == 16000);
  194. luat_airtalk_net_transfer_start(mode);
  195. luat_airtalk_speech_record_switch(1);
  196. break;
  197. case LUAT_AIRTALK_SPEECH_MODE_GROUP_SPEAKER:
  198. luat_airtalk_use_16k(sample == 16000);
  199. luat_airtalk_speech_record_switch(1);
  200. luat_airtalk_net_transfer_start(mode);
  201. break;
  202. case LUAT_AIRTALK_SPEECH_MODE_GROUP_LISTENER:
  203. luat_airtalk_use_16k(sample == 16000);
  204. luat_airtalk_speech_start_play(sample == 16000);
  205. luat_airtalk_net_transfer_start(mode);
  206. break;
  207. }
  208. }
  209. else
  210. {
  211. luat_airtalk_net_transfer_stop();
  212. luat_airtalk_speech_record_switch(0);
  213. }
  214. return 0;
  215. }
  216. ///*
  217. //airtalk上行控制
  218. //@api airtalk.uplink(on_off)
  219. //@boolean 录音上行控制,true开始,false停止
  220. //@return nil
  221. //@usage
  222. //--开始录音
  223. //airtalk.uplink(true)
  224. //--停止录音
  225. //airtalk.uplink(false)
  226. //*/
  227. //static int l_airtalk_uplink(lua_State *L)
  228. //{
  229. // luat_airtalk_speech_record_switch(lua_toboolean(L, 1));
  230. // return 0;
  231. //}
  232. /*
  233. airtalk的详细调试信息开关
  234. @api airtalk.debug(on_off)
  235. @boolean 调试信息开关,true打开,false关闭
  236. @return nil
  237. */
  238. static int l_airtalk_debug(lua_State *L)
  239. {
  240. uint8_t on_off = lua_toboolean(L, 1);
  241. luat_airtalk_net_debug_switch(on_off);
  242. luat_airtalk_speech_debug_switch(on_off);
  243. return 0;
  244. }
  245. #include "rotable2.h"
  246. static const rotable_Reg_t reg_airtalk[] =
  247. {
  248. { "speech", ROREG_FUNC(l_airtalk_speech)},
  249. { "config", ROREG_FUNC(l_airtalk_config)},
  250. { "on", ROREG_FUNC(l_airtalk_on)},
  251. { "start", ROREG_FUNC(l_airtalk_start)},
  252. { "set_ssrc", ROREG_FUNC(l_airtalk_set_ssrc)},
  253. { "set_topic", ROREG_FUNC(l_airtalk_set_mqtt_topic)},
  254. // { "uplink", ROREG_FUNC(l_airtalk_uplink)},
  255. { "debug", ROREG_FUNC(l_airtalk_debug)},
  256. //@const PROTOCOL_MQTT number 语音数据用MQTT传输
  257. { "PROTOCOL_MQTT", ROREG_INT(LUAT_AIRTALK_PROTOCOL_MQTT)},
  258. //@const MODE_PERSON number 对讲工作模式1对1
  259. { "MODE_PERSON", ROREG_INT(LUAT_AIRTALK_SPEECH_MODE_PERSON)},
  260. //@const MODE_GROUP_SPEAKER number 对讲工作模式1对多的发起者,录音上行,不播放
  261. { "MODE_GROUP_SPEAKER", ROREG_INT(LUAT_AIRTALK_SPEECH_MODE_GROUP_SPEAKER)},
  262. //@const MODE_GROUP_LISTENER number 对讲工作模式1对多的接收者,下行播放,不录音
  263. { "MODE_GROUP_LISTENER", ROREG_INT(LUAT_AIRTALK_SPEECH_MODE_GROUP_LISTENER)},
  264. //@const EVENT_OFF_LINE number airtalk离线
  265. { "EVENT_OFF_LINE", ROREG_INT(LUAT_AIRTALK_CB_ON_LINE_IDLE)},
  266. //@const EVENT_ON_LINE_IDLE number airtalk在线处于空闲状态
  267. { "EVENT_ON_LINE_IDLE", ROREG_INT(LUAT_AIRTALK_CB_ON_LINE_IDLE)},
  268. //@const EVENT_PLAY_START number airtalk下行播放开始
  269. { "EVENT_PLAY_START", ROREG_INT(LUAT_AIRTALK_CB_PLAY_START)},
  270. //@const EVENT_PLAY_END number airtalk下行播放结束
  271. { "EVENT_PLAY_END", ROREG_INT(LUAT_AIRTALK_CB_PLAY_END)},
  272. //@const EVENT_RECORD_START number airtalk录音上行开始
  273. { "EVENT_RECORD_START", ROREG_INT(LUAT_AIRTALK_CB_RECORD_START)},
  274. //@const EVENT_RECORD_END number airtalk录音上行结束
  275. { "EVENT_RECORD_END", ROREG_INT(LUAT_AIRTALK_CB_RECORD_END)},
  276. //@const EVENT_AUDIO_START number airtalk audio启动,只要上行和下行有一个开始就启动
  277. { "EVENT_AUDIO_START", ROREG_INT(LUAT_AIRTALK_CB_AUDIO_START)},
  278. //@const EVENT_AUDIO_END number airtalk audio停止,上行和下行都结束才停止
  279. { "EVENT_AUDIO_END", ROREG_INT(LUAT_AIRTALK_CB_AUDIO_END)},
  280. //@const EVENT_ERROR number airtalk发生异常,后续param为异常值
  281. { "EVENT_ERROR", ROREG_INT(LUAT_AIRTALK_CB_ERROR)},
  282. { NULL, ROREG_INT(0) }
  283. };
  284. LUAMOD_API int luaopen_airtalk(lua_State *L)
  285. {
  286. luat_newlib2(L, reg_airtalk);
  287. return 1;
  288. }
  289. LUAT_WEAK void luat_airtalk_callback(uint32_t event, void *param, uint32_t param_len)
  290. {
  291. rtos_msg_t msg = {0};
  292. msg.handler = l_airtalk_handler;
  293. msg.ptr = param;
  294. msg.arg1 = event;
  295. msg.arg2 = param_len;
  296. luat_msgbus_put(&msg, 0);
  297. }