1. 程式人生 > 其它 >Luat Demo | 給我十分鐘,教你實現Cat.1語音通話功能!

Luat Demo | 給我十分鐘,教你實現Cat.1語音通話功能!

語音通話是Cat.1模組的重要應用功能之一,合宙官方提供了Luat Demo,便於廣大客戶在手機、對講機、電話手錶等終端開發中參考運用。

合宙Cat.1系列中,Air720UH模組支援4G+2G,可直接使用語音通話功能;其他只支援4G制式的模組(如Air720UG、Air724UG),均需先開啟VoLTE功能才能進行語音通話。

本文將以Air724UG開發板為例進行實操演示,Demo原始碼可通過LuaTools或LuatIDE獲取。

前期主要準備工作


硬體準備:

EVB_Air724UG_A13開發板(本文操作適用於合宙Cat.1系列的開發板),以及天線、SIM卡、USB線。

軟體準備:

Windows電腦搭建Luat開發環境,可參考下文:

https://doc.openluat.com/wiki/21?wiki_page_id=1923

API說明:

https://doc.openluat.com/wiki/21?wiki_page_id=2267

通話功能Demo實操演示


例程參考:

CALL通話功能相關例項程式,在LuaTools/LuatIDE指令碼庫的demo\call資料夾下。

最新版LuatIDE下載:

https://marketplace.visualstudio.com/items?itemName=luater.luatide


指令碼邏輯:


1)訂閱資訊函式

通話的相關事件是通過訊息驅動的,首先通過sys.subscribe()註冊訊息處理函式。我們通過訂閱來電、接通、結束訊息的處理函式,來做不同場景的處理。

sys.subscribe("CALL_INCOMING",incoming)
sys.subscribe("CALL_CONNECTED",connected)
sys.subscribe("CALL_DISCONNECTED",disconnected)


2)播放來電鈴音

通過來電訊息處理函式,當有電話打進來的時候,模組會上報CALL_INCOMING來電的訊息,我們在上面註冊的訊息回撥函式incoming()裡去做處理。

此處主要是播放來電鈴音,也可以通過TTS方式播放一段語言,同時註冊了一個按鍵訊息用於接通電話。

local function incoming(num)
    log.info("testCall.incoming:"..num)    
    if not coIncoming then
        coIncoming = sys.taskInit(function()
            while true do
                --audio.play(1,"TTS","來電話啦",4,function() sys.publish("PLAY_INCOMING_RING_IND") end,true)
                audio.play(1,"FILE","/lua/call.mp3",4,function() sys.publish("PLAY_INCOMING_RING_IND") end,true)
                sys.waitUntil("PLAY_INCOMING_RING_IND")       
               break                

            end
        end)
        sys.subscribe("POWER_KEY_IND",function() audio.stop(function() cc.accept(num) end) end) 
     end     
end


3)接通來電

通過註冊開機鍵的訊息來接通電話,收到POWER_KEY_IND按鍵訊息後,先停止之前的來電鈴聲,然後呼叫cc.accept()函式來接電話。

sys.subscribe("POWER_KEY_IND",function() audio.stop(function() cc.accept(num) end) end)


4)設定mic增益等級及相關操作

通話建立,電話接通後會上報CALL_CONNECTED訊息。此時我們就可以在上面註冊的connected()函式裡做想做的事情了。

比如:設定MIC增益,呼叫callVolTest()介面5秒鐘調節一次音量,通過TTS播放的方式向對面播放一段語音,最後啟動一個110S的定時器通過cc.hangUp()結束通話電話。

local function callVolTest()
    local curVol = audio.getCallVolume()
    curVol = (curVol>=7) and 1 or (curVol+1)  
    log.info("testCall.setCallVolume",curVol)

    audio.setCallVolume(curVol)
end

local function connected(num)

      log.info("testCall.connected")
      coIncoming = nil
      --通話中設定mic增益,必須在通話建立以後設定
      --audio.setMicGain("call",7)
      --通話中音量測試
      sys.timerLoopStart(callVolTest,5000)    
      --通話中向對方播放TTS測試

      audio.play(7,"TTS","通話中TTS測試",7,nil,true,2000)    
       --110秒之後主動結束通話

       sys.timerStart(cc.hangUp,110000,num)
end


5)結束通話電話

通話結束,電話結束通話之後會上報CALL_DISCONNECTED訊息,用來通知通話結束。在disconnected()訊息處理函式中,主要是置位一些變數,停止之前開啟的定時器、音訊播放等。

local function disconnected() 

           coIncoming = nil 

           log.info("testCall.disconnected")  

           sys.timerStopAll(cc.hangUp) 

           sys.timerStop(callVolTest)

           audio.stop()          

    end


6)撥打電話

這裡是在收到網路註冊NET_STATE_REGISTERED的訊息後,啟動了一個定時器10秒後通過呼叫cc.dial()來撥打電話。

  --- “通話功能模組準備就緒””訊息處理函式
         -- @return 無
         local function ready()

                log.info("tesCall.ready")    --呼叫10086
                sys.timerStart(cc.dial,10000,"10086")
         end


7)通話過程中給對方播放音訊

新增demo/audio/testAudioStream.lua的testAudioStream.,在以下程式碼中新增引數audiocore.PLAY_VOLTE:

curr_len = curr_len +
audiocore.streamplay(tStreamType,string.sub(data,curr_len,-1),audiocore.PLAY_VOLTE)

local function testAudioStream(streamType)
    sys.taskInit(      
         function()   
              while true do       
                       tStreamType = streamType           
                       log.info("AudioTest.AudioStreamTest", "AudioStreamPlay Start", streamType)                  
                     local tAudioFile =           
                     {
                 
                           [audiocore.AMR] = "tip.amr",  
                           [audiocore.SPX] = "record.spx",    
                           [audiocore.PCM] = "alarm_door.pcm",
             
                           [audiocore.MP3] = "sms.mp3"  
                       }              
                      local fileHandle = io.open("/lua/" .. tAudioFile[streamType], "rb")   
                     if not fileHandle then                        
                     log.error("AudioTest.AudioStreamTest", "Open file error")               
                           return     
                     end

        
       
                     while true do      
                           local data = fileHandle:read(streamType == audiocore.SPX and 1200 or 1024)        
                            if not data then                  
                                                   fileHandle:close() 
                                       while audiocore.streamremain() ~= 0 do   
                                       sys.wait(20)	
                
                                   end
               
                             sys.wait(1000)   
                             audiocore.stop()  --新增audiocore.stop()介面,否則再次播放會播放不出來 
                     log.warn("AudioTest.AudioStreamTest", "AudioStreamPlay Over")                      
                   return 
		    
                          end

                  

                    local data_len = string.len(data)   
                    local curr_len = 1    
                     while true do
               
                          curr_len = curr_len + audiocore.streamplay(tStreamType,string.sub(data,curr_len,-1),audiocore.PLAY_VOLTE)                  
                           if curr_len>=data_len then
   
                                break
                  
                           elseif curr_len == 0 then
                     log.error("AudioTest.AudioStreamTest", "AudioStreamPlay Error", streamType)                                                     return 
                          end    
                          sys.wait(10)         
                    end     
                    sys.wait(10)        
              end
         end    
    end
    )
end    

在connected新增一行testAudioStream(audiocore.AMR) ,新增tip.amr燒錄。除錯電話接通後對方即有tip.amr的音訊播放。

通話功能常見問題


打不了電話,如何排查原因:

確認能不能正常註冊上網路,有沒有欠費;

確認是否開通VoLTE功能,只有開通VoLTE功能才能進行語音通話;

確認韌體是否支援VoLTE功能。

除錯天線時,如何設定來電自動接聽:

ril.regUrc(“RING”,function()ril.request(“ATA”) end)

Cat.1是否支援視訊通話?

不支援

mic增益設定:

audio.setMicGain()通話中設定mic增益,必須在通話建立以後設定。

韌體是否支援VoLTE:

可以通過韌體名稱判斷,帶有NOVoLTE標誌的,說明不支援VoLET。 也可以通過AT口傳送AT+SETVOLTE?查詢,0
表示關閉VoLET,1表示開啟VoLET功能。

上海合宙通訊模組 - 合宙Luat,讓萬物互聯更簡單