Explorar o código

Merge branch 'master' of gitee.com:openLuat/LuatOS

Wendal Chen hai 7 meses
pai
achega
bbd58433b1

+ 56 - 16
components/airtalk/binding/luat_lib_airtalk.c

@@ -139,6 +139,30 @@ static int l_airtalk_start(lua_State *L)
     luat_airtalk_net_init();
     return 0;
 }
+/*
+配置airtalk RTP协议中的SSRC
+@api airtalk.set_ssrc(ssrc)
+@int/string ssrc,可以是int也是可以8字节string
+@return nil
+@usage
+
+*/
+static int l_airtalk_set_ssrc(lua_State *L)
+{
+	if (lua_isstring(L, 1))
+	{
+		size_t len;
+	    const char *id = lua_tolstring(L, 1, &len);//取出字符串数据;
+	    uint32_t ssrc = strtol(id, NULL, 16);
+	    luat_airtalk_net_set_ssrc(ssrc);
+	}
+	else
+	{
+		luat_airtalk_net_set_ssrc(lua_tointeger(L, 1));
+	}
+
+    return 0;
+}
 
 /*
 配置airtalk mqtt类型语音数据的专用topic
@@ -157,29 +181,44 @@ static int l_airtalk_set_mqtt_topic(lua_State *L)
 }
 
 /*
-airtalk工作启动/停止
-@api airtalk.speech(mode, on_off)
-@int  工作模式,见airtalk.MODE_XXX
-@boolean  启停控制,true开始,false停止
+airtalk对讲工作启动/停止
+@api airtalk.speech(on_off, mode, sample)
+@boolean 启停控制,true开始,false停止
+@int 工作模式,见airtalk.MODE_XXX
+@int 音频采样率,目前只有8000和16000,默认16000
 @return nil
 @usage
 --1对1对讲开始
-airtalk.speech(airtalk.MODE_PERSON,true)
+airtalk.speech(true,airtalk.MODE_PERSON,16000)
 --1对多对讲开始
-airtalk.speech(airtalk.MODE_GROUP,true)
+airtalk.speech(true,airtalk.MODE_GROUP,16000)
+--对讲停止
+airtalk.speech(false)
 */
 static int l_airtalk_speech(lua_State *L)
 {
-	int mode = luaL_optinteger(L, 1, LUAT_AIRTALK_SPEECH_MODE_PERSON);
-	int on_off = lua_toboolean(L, 2);
-	switch(mode)
+	int mode = luaL_optinteger(L, 2, LUAT_AIRTALK_SPEECH_MODE_PERSON);
+	int sample = luaL_optinteger(L, 3, 16000);
+	int on_off = lua_toboolean(L, 1);
+	if (on_off)
 	{
-	case LUAT_AIRTALK_SPEECH_MODE_PERSON:
-
-		luat_airtalk_speech_record_switch(lua_toboolean(L, 1));
-		break;
-	case LUAT_AIRTALK_SPEECH_MODE_GROUP:
-		break;
+		switch(mode)
+		{
+		case LUAT_AIRTALK_SPEECH_MODE_PERSON:
+			luat_airtalk_use_16k(sample == 16000);
+			luat_airtalk_net_transfer_start(mode);
+			luat_airtalk_speech_record_switch(1);
+			break;
+		case LUAT_AIRTALK_SPEECH_MODE_GROUP:
+			luat_airtalk_use_16k(sample == 16000);
+			luat_airtalk_net_transfer_start(mode);
+			break;
+		}
+	}
+	else
+	{
+		luat_airtalk_net_transfer_stop();
+		luat_airtalk_speech_record_switch(0);
 	}
 
     return 0;
@@ -220,11 +259,12 @@ static int l_airtalk_debug(lua_State *L)
 #include "rotable2.h"
 static const rotable_Reg_t reg_airtalk[] =
 {
+	{ "speech",      ROREG_FUNC(l_airtalk_speech)},
     { "config",      ROREG_FUNC(l_airtalk_config)},
     { "on",         ROREG_FUNC(l_airtalk_on)},
     { "start",      ROREG_FUNC(l_airtalk_start)},
+	{ "set_ssrc",      ROREG_FUNC(l_airtalk_set_ssrc)},
 	{ "set_topic",      ROREG_FUNC(l_airtalk_set_mqtt_topic)},
-	{ "speech",      ROREG_FUNC(l_airtalk_speech)},
     { "uplink",      ROREG_FUNC(l_airtalk_uplink)},
 	{ "debug",      ROREG_FUNC(l_airtalk_debug)},
 	//@const PROTOCOL_MQTT number 语音数据用MQTT传输

+ 14 - 5
components/airtalk/core/airtalk_network.c

@@ -33,7 +33,7 @@ typedef struct
 static airtalk_network_ctrl_t prv_network;
 
 //播放完成
-static void end_broadcast_play(void)
+static void airtalk_full_stop(void)
 {
 	net_data_struct *net_cache;
 	luat_airtalk_speech_stop_play();
@@ -296,9 +296,12 @@ TX_DATA_DONE:
 			sync_lost = 1;
 			break;
 		case AIRTALK_EVENT_NETWORK_FORCE_STOP:
-			sync_lost = 1;
-			prv_network.is_ready = 0;
-			end_broadcast_play();
+			if (prv_network.is_ready)
+			{
+				sync_lost = 1;
+				prv_network.is_ready = 0;
+				airtalk_full_stop();
+			}
 			break;
 		case AIRTALK_EVENT_NETWORK_MSG:
 			break;
@@ -320,8 +323,14 @@ void luat_airtalk_net_param_config(uint8_t audio_data_protocl, uint32_t download
 	prv_network.download_cache_time = download_cache_time;
 }
 
-void luat_airtalk_net_transfer_start(void)
+void luat_airtalk_net_set_ssrc(uint32_t ssrc)
+{
+	prv_network.local_ssrc = ssrc;
+}
+
+void luat_airtalk_net_transfer_start(uint8_t work_mode)
 {
+	prv_network.work_mode = work_mode;
 	luat_rtos_event_send(prv_network.task_handle, AIRTALK_EVENT_NETWORK_READY_START, 0, 0, 0, 0);
 }
 

+ 2 - 1
components/airtalk/include/airtalk_api.h

@@ -14,7 +14,8 @@ void luat_airtalk_net_init(void);
 void *luat_airtalk_net_common_init(CBDataFun_t send_function, CBDataFun_t recv_function);
 void luat_airtalk_net_param_config(uint8_t audio_data_protocl, uint32_t download_cache_time);
 void luat_airtalk_net_debug_switch(uint8_t on_off);
-void luat_airtalk_net_transfer_start(void);
+void luat_airtalk_net_set_ssrc(uint32_t ssrc);
+void luat_airtalk_net_transfer_start(uint8_t work_mode);
 void luat_airtalk_net_transfer_stop(void);
 void luat_airtalk_net_save_uplink_head(uint64_t record_time);
 void luat_airtalk_net_save_uplink_data(uint8_t *data, uint32_t len);

+ 1 - 0
components/airtalk/include/airtalk_def.h

@@ -52,6 +52,7 @@ typedef struct
 	uint8_t is_ready;
 	uint8_t audio_data_protocl;
 	uint8_t is_16k;
+	uint8_t work_mode;
 	uint8_t debug_on_off;
 }airtalk_network_ctrl_t;
 #endif

+ 151 - 29
luat/demo/airtalk/airtalk_net_ctrl.lua

@@ -1,8 +1,9 @@
-require "audio_config"
 
-
-local mqttc = nil
+local speech_state = SP_T_IDLE
+local speech_mdoe
+local g_mqttc = nil
 local client_id
+local downlink_topic
 local topic_auth
 local topic_list_update
 local topic_talk_start
@@ -10,6 +11,9 @@ local topic_talk_stop
 local topic_list_update_ack
 local topic_talk_start_ack
 local topic_talk_stop_ack
+local speech_topic
+local speech_sample
+local dev_list
 
 local function task_cb(msg)
     log.info("未处理消息", msg[1], msg[2], msg[3], msg[4])
@@ -19,29 +23,136 @@ local function airtalk_event_cb(event, param)
     log.info("airtalk event", event, param)
 end
 
-local function mqtt_cb(mqtt_client, event, data, payload)
-    log.info(event)
+local function next_auth()
+    if speech_state == SP_T_IDLE then
+        obj = {["key"] = PRODUCT_KEY, ["device_type"] = 1}
+        data = json.encode(obj)
+        log.info(topic_auth, data)
+        mqttc:publish(topic_auth, data)
+    end
+end
+
+local function mqtt_cb(mqttc, event, topic, payload)
+    -- log.info(event)
+    local msg,data,obj,speech_topic,speech_sample
     if event == "conack" then
         -- 联上了
-        mqtt_client:subscribe("ctrl/downlink/" .. client_id .. "/#")--单主题订阅
+        mqttc:subscribe("ctrl/downlink/" .. client_id .. "/#")--单主题订阅
     elseif event == "suback" then
-        sys.sendMsg(AIRTALK_TASK_NAME, MSG_MQTT_READY)
+        if speech_state == SP_T_IDLE then
+            obj = {["key"] = PRODUCT_KEY, ["device_type"] = 1}
+            data = json.encode(obj)
+            log.info(topic_auth, data)
+            mqttc:publish(topic_auth, data)
+            sys.timerLoopStart(next_auth, 60000)    --1分钟就尝试重新鉴权
+        elseif speech_state == SP_T_CONNECTING then
+            speech_state = SP_T_CONNECTED
+            obj = {["result"] = SUCC, ["topic"] = msg[2], ["info"] = ""}
+            data = json.encode(obj)
+            log.info(topic_talk_start_ack, data)
+            mqttc:publish(topic_talk_start_ack, data)
+            airtalk.speech(true, speech_mdoe, speech_sample)
+        else
+            
+        end 
+        
     elseif event == "recv" then
-        log.info("mqtt", "downlink", "topic", data, payload)
+        local result = string.match(topic, downlink_topic)
+        if result then
+            log.info(topic, payload)
+            local obj,res,err = json.decode(payload)
+            if result == "0102" then
+                if res and obj["topic"] and obj["ssrc"] and obj["audio_code"] then
+                    if speech_state == SP_T_CONNECTED then
+                        obj = {["result"] = "failed", ["topic"] = msg[2], ["info"] = "last speech is running"}
+                        data = json.encode(obj)
+                        log.info(topic_talk_start_ack, data)
+                        mqttc:publish(topic_talk_start_ack, data)
+                        airtalk.speech(true, speech_mdoe, speech_sample)
+                    elseif speech_state == SP_T_DISCONNECTING then
+                        obj = {["result"] = "failed", ["topic"] = msg[2], ["info"] = "last speech not stop"}
+                        data = json.encode(obj)
+                        log.info(topic_talk_start_ack, data)
+                        mqttc:publish(topic_talk_start_ack, data)
+                        airtalk.speech(true, speech_mdoe, speech_sample)
+                    else
+                        speech_state = SP_T_CONNECTING
+                        speech_topic = msg[2]
+                        speech_sample = msg[4] == "amr-nb" and 8000 or 16000
+                        mqttc:subscribe(speech_topic)
+                        airtalk.set_topic(speech_topic)
+                        airtalk.set_ssrc(msg[3])
+                        speech_mdoe = airtalk.MODE_PERSON
+                    end
+                else
+                    obj = {["result"] = "failed", ["info"] = "json info error"}
+                    data = json.encode(obj)
+                    log.info(topic_talk_start_ack, data)
+                    mqttc:publish(topic_talk_start_ack, data)
+                end
+            elseif result == "0103" then
+                if speech_state == SP_T_IDLE then
+                    obj = {["result"] = "failed", ["info"] = "no speech"}
+                else
+                    obj = {["result"] = SUCC, ["info"] = ""}
+                    speech_state = SP_T_IDLE
+                    mqttc:unsubscribe(speech_topic)
+                    airtalk.speech(false)
+                    speech_topic = nil
+                end
+                data = json.encode(obj)
+                mqttc:publish(topic_talk_stop_ack, data)
+            elseif result == "0101" then
+                if res then
+                    dev_list = obj["dev_list"]
+                    for i=1,#dev_list do
+                        log.info(dev_list[i]["id"],dev_list[i]["name"])
+                    end
+                    obj = {["result"] = SUCC, ["info"] = ""}
+                else
+                    obj = {["result"] = "failed", ["info"] = "json info error"}
+                end
+                data = json.encode(obj)
+                log.info(topic_list_update_ack, data)
+                mqttc:publish(topic_list_update_ack, data)
+            elseif result == "8003" then
+            elseif result == "8004" then
+            elseif result == "8001" then
+                if res and obj["result"] then
+                    sys.timerLoopStart(next_auth, 3600000) --鉴权通过则60分钟后尝试重新鉴权
+                    mqttc:publish(topic_list_update, "")
+                end
+            elseif result == "8002" then
+                if res and obj["result"] == SUCC then
+                    dev_list = obj["dev_list"]
+                    for i=1,#dev_list do
+                        log.info(dev_list[i]["id"],dev_list[i]["name"])
+                    end
+                    sys.sendMsg(USER_TASK_NAME, MSG_READY)
+                end
+            else
+            end
+            decode_data = nil
+        end
+        result = nil
+        data = nil
+        obj = nil
+        
     elseif event == "sent" then
         -- log.info("mqtt", "sent", "pkgid", data)
-    -- elseif event == "disconnect" then
+    elseif event == "disconnect" then
+        speech_state = SP_T_IDLE
         -- 非自动重连时,按需重启mqttc
-        -- mqtt_client:connect()
+        -- mqttc:connect()
     else
     end
 end
 
 function airtalk_mqtt_task()
-    local msg,data,obj
+    local msg,data,obj,speech_topic,speech_sample
     --client_id也可以自己设置
     client_id = mobile.imei()
-
+    downlink_topic = "ctrl/downlink/" .. client_id .. "/(%w%w%w%w)"
     topic_auth = "ctrl/uplink/" .. client_id .."/0001"
     topic_list_update = "ctrl/uplink/" .. client_id .."/0002"
     topic_talk_start = "ctrl/uplink/" .. client_id .."/0003" 
@@ -49,34 +160,45 @@ function airtalk_mqtt_task()
     topic_list_update_ack = "ctrl/uplink/" .. client_id .."/8101"
     topic_talk_start_ack = "ctrl/uplink/" .. client_id .."/8102"
     topic_talk_stop_ack = "ctrl/uplink/" .. client_id .."/8103"
+    sys.timerLoopStart(next_auth, 900000)
 
-
-    audio_init()
-
-    mqttc = mqtt.create(nil, "mqtt.airtalk.luatos.com", 1883, false, {rxSize = 4096})
-    airtalk.config(airtalk.PROTOCOL_MQTT, mqttc, 200) -- 缓冲至少200ms播放
+    g_mqttc = mqtt.create(nil, "mqtt.airtalk.luatos.com", 1883, false, {rxSize = 32768})
+    airtalk.config(airtalk.PROTOCOL_MQTT, g_mqttc, 200) -- 缓冲至少200ms播放
     airtalk.on(airtalk_event_cb)
     airtalk.start()
 
-    mqttc:auth(client_id,client_id,mobile.muid()) -- client_id必填,其余选填
-    mqttc:keepalive(240) -- 默认值240s
-    mqttc:autoreconn(true, 3000) -- 自动重连机制
-    mqttc:debug(false)
-    mqttc:on(mqtt_cb)
+    g_mqttc:auth(client_id,client_id,mobile.muid()) -- client_id必填,其余选填
+    g_mqttc:keepalive(240) -- 默认值240s
+    g_mqttc:autoreconn(true, 3000) -- 自动重连机制
+    g_mqttc:debug(false)
+    g_mqttc:on(mqtt_cb)
 
     -- mqttc自动处理重连, 除非自行关闭
-    mqttc:connect()
+    g_mqttc:connect()
     while true do
         msg = sys.waitMsg(AIRTALK_TASK_NAME)
-        if type(msg) == 'table' and type(msg[1]) == "number" and msg[1] < 5 then
-            if msg[1] == MSG_MQTT_READY then
-                obj = {["key"] = PRODUCT_KEY, ["device_type"] = 1}
+        if type(msg) == 'table' and type(msg[1]) == "number" then
+            if msg[1] == MSG_PERSON_SPEECH_REQ then
+                -- if speech_state = 
+                -- speech_state = SP_T_CONNECTING
+                -- obj = {["to"] = msg[2]}
+                -- data = json.encode(obj)
+                -- log.info(topic_talk_start, data)
+                -- mqttc:publish(topic_talk_start, data)
+            elseif msg[1] == MSG_SPEECH_STOP_REQ then
+                speech_state = SP_T_IDLE
+                mqttc:unsubscribe(speech_topic)
+                airtalk.speech(false)
+                speech_topic = nil
                 data = json.encode(obj)
-                log.info(topic_auth, data)
-                mqttc:publish(topic_auth, data)
-                obj = nil
+                log.info(topic_talk_stop, data)
+                mqttc:publish(topic_talk_stop, data)
             end
+            obj = nil
+        else
+            log.info(type(msg), type(msg[1]))
         end
+        msg = nil
     end
 end
 

+ 18 - 1
luat/demo/airtalk/demo_define.lua

@@ -1,3 +1,20 @@
 
 AIRTALK_TASK_NAME = "airtalk_task"
-MSG_MQTT_READY = 0
+USER_TASK_NAME = "user"
+MSG_PERSON_SPEECH_REQ = 0
+MSG_SPEECH_STOP_REQ = 1
+MSG_PERSON_SPEECH_ACK = 2
+MSG_SPEECH_STOP_ACK = 3
+MSG_SPEECH_IND = 4
+MSG_READY = 10
+MSG_NOT_READY = 11
+MSG_KEY_PRESS = 12
+
+
+
+SP_T_IDLE = 0
+SP_T_CONNECTING = 1
+SP_T_CONNECTED = 2
+SP_T_DISCONNECTING = 3
+
+SUCC = "success"

+ 46 - 3
luat/demo/airtalk/main.lua

@@ -1,12 +1,56 @@
 PROJECT = "airtalk_demo"
 VERSION = "1.0.1"
-PRODUCT_KEY = "1234" -- 到 iot.openluat.com 创建项目,获取正确的项目id
+PRODUCT_KEY = "s1uUnY6KA06ifIjcutm5oNbG3MZf5aUv" -- 到 iot.openluat.com 创建项目,获取正确的项目id
 log.style(1)
 require "demo_define"
 require "airtalk_net_ctrl"
+require "audio_config"
 
+errDump.config(true, 600, "airtalk_test")
+
+local function key_cb()
+
+end
+
+--按下boot开始上传,再按下停止,加入了软件去抖,不需要长按了
+gpio.setup(0, key_cb, gpio.PULLDOWN, gpio.RISING)
+gpio.debounce(0, 200, 1)
+
+local test_ready = false
+local function task_cb(msg)
+    log.info("未处理消息", msg[1], msg[2], msg[3], msg[4])
+    if msg[1] == MSG_SPEECH_IND then
+
+    elseif msg[1] == MSG_NOT_READY then
+        test_ready = false
+        msg = sys.waitMsg(USER_TASK_NAME, MSG_KEY_PRESS)
+    end
+end
+
+local function user_task()
+    audio_init()
+    airtalk_mqtt_init()
+    local msg
+    while true do
+        msg = sys.waitMsg(USER_TASK_NAME, MSG_READY)
+        log.info("airtalk准备好了")
+        test_ready = true
+        while test_ready do
+            msg = sys.waitMsg(USER_TASK_NAME, MSG_KEY_PRESS)
+            if test_ready then
+                sys.sendMsg(AIRTALK_TASK_NAME, MSG_PERSON_SPEECH_REQ, "")   --测试阶段自动给一个device打
+                msg = sys.waitMsg(USER_TASK_NAME, MSG_PERSON_SPEECH_ACK)
+                msg = sys.waitMsg(USER_TASK_NAME, MSG_KEY_PRESS)
+                sys.sendMsg(AIRTALK_TASK_NAME, MSG_SPEECH_STOP_REQ) 
+                msg = sys.waitMsg(USER_TASK_NAME, MSG_SPEECH_STOP_ACK)
+            end
+        end
+        log.info("airtalk断线了")
+    end
+end
+
+sys.taskInitEx(user_task, USER_TASK_NAME, task_cb)
 
-airtalk_mqtt_init()
 --定期检查ram使用情况,及时发现内存泄露
 sys.taskInit(function()
     while true do
@@ -17,5 +61,4 @@ sys.taskInit(function()
         log.info("psram", rtos.meminfo("psram"))
     end
 end)
-
 sys.run()