Search code examples
javascriptdialogflow-esvoximplant

How can I aggregate multiple DTMF keys with Voximplant?


I am able to dial one digit with DTMF by calling into Voximplant who is connected with DialogFlow. I have followed this scenario, but as the code states in line 147, // ToDo: aggregate multiple DTMF keys that are pressed in succession and send as a single string.

Have anyone been able to dial inn more than one digit or could guide me to the correct example of doing this?


Solution

  • I have made a more comprehensive example for Voximplant that handles multiple DTMF entry. This requires a few extra parameters to control how many digits and when to stop collecting DTMF before reporting it back:

    // Configurable via custom payload
    let interToneTime = 3000               // Default time to wait for the next DTMF digit after one is pressed
    let maxToneDigits = 12                 // Default number of DTMF digits to look for after one is pressed
    let dtmfMode = "event"                 // Send DTMF key presses as events or as "text"
    let stopTones = []                     // DTMF tones used to indicate end of digit entry
    

    I then expanded on the original onTone function in the DTMF example from cogint.ai you linked to:

    function onTone(e) {
      Logger.write("DEBUG: onTone called: " + e.tone) // on iteration #" + cnt)
    
      if (stopTones.includes(e.tone)){
        Logger.write("DEBUG: stopTone entered: " + e.tone);
        toneTimerCallback()
        return
      }
    
      noInputTimer.stop()
      toneCount++;
      tones.push(e.tone)
    
      if (toneCount >= maxToneDigits){
        Logger.write("DEBUG: maximum number of specified tones reached: " + toneCount) // on iteration #" + cnt)
        toneTimerCallback()
      }
      else
        toneTimer.start()
    
    }
    

    This essentially pushes the tone into an array and calls the toneTimerCallback function if a stop tone is pressed (i.e. this is usually # or *) or if maxToneDigits is exceeded.

    The toneTimerCallback just converts the digits to a string and sends them to Dialogflow:

    function toneTimerCallback() {
      let toneString = tones.join('').toString()  // bug requires adding an extra .toString()
      
      if (toneString == '') {
        Logger.write("DEBUG: toneTimerCallback - invalid toneString: " + toneString)
        return
      }
    
      Logger.write("DEBUG: sending DTMF in " + dtmfMode + "mode : " + toneString)
      if (dtmfMode == "event")
        dialogflow.sendQuery({ event: { name: "DTMF", language_code: "en", parameters: { dtmf_digits: toneString } } })
      else if (dtmfMode == "text")
         dialogflow.sendQuery({ text: { text: toneString.toString(),  language_code: "en" }}) // bug requires adding an extra .toString()
    
      toneCount = 0
      tones = []
    }
    

    This shows how to send the digits as a text input or as an event.

    Other related parts in the gist show how to set these parameters on a per-intent basis using custom payloads. This for example, could let you specify a max of 5 digits for a ZIP code in one intent and set 10 for another that asks for a phone number.