Twilio not dialing always - twilio

we are using Twilio agent-dialing to initiate the call between two users.
User A request a call to user B
We get the number from the WS, then create a call with Twilio
Twilio dials user A SOMETIMES fails here
When user A answers, then Twilio dials user B
This works fine most of the time, but some times the call is not even initiated. We get the call.getSid() as if the call was launched, but the phone never rings.
if (!from.equals(to)) {
Twilio.init(TWILIO_ACCOUNT_SID, TWILIO_ACCOUNT_TOKEN);
try {
final String encodedNumber = URLEncoder.encode(to, "UTF-8");
final String url = URL + "/connect/" + encodedNumber;
final Call call = Call.creator(new PhoneNumber(from), new PhoneNumber(TWILIO_PHONE_NUMBER), new URI(url)).setTimeout(20).create();
response.setMessage("Calling " + response.getItem().getDisplayName() + "'s " + params.getNumberType() + "...");
LoggerUtil.out("Call done through Twilio: " + call.getSid() + " from: " + from + " to: " + to);
} catch (UnsupportedEncodingException | URISyntaxException ex) {
ex.printStackTrace();
response.setMessage("I cannot dial " + response.getItem().getDisplayName() + "'s " + params.getNumberType() + " now, please try again later.");
}
} else {
response.setMessage("You cannot call yourself.");
}
OUTPUT: Call done through Twilio: CAabf9ba78b3b94921b000cda2ae6d2b91 from: +521234567890 to: +520987654321
And, on Twilio console there are no errors on either. Also, we noticed that the $ decreases, which means we got charged (non-trial account), as the "call was made", but it was not.
Does anybody faced same issue? The same happens SOMETIMES, for the Agent side (bullet #4 on above steps): User A answers, but user B is never called (no dialing sound or anything at all on the user A phone, just void):
final Dial dial = new Dial.Builder().number(number).build();
final VoiceResponse voiceResponse = new VoiceResponse.Builder().dial(dial).build();
As said, this is happening sometimes, and most of the times for non-US phones (it also happens for US ones, but in small rates).
Thanks in advance.

Check the Twilio Call Logs to validate that we have successfully received and processed the incoming call(s). You can view the logs and search for your call record via either Console, or the REST API.
A record doesn't exist for the call: If you don't see a record for the call in question, then there is likely an issue elsewhere. Continue reading for additional troubleshooting.
A record does exist for the call: If you do see a record for the call in question, this indicates Twilio has successfully received the call, and the issue lies elsewhere. Continue troubleshooting with the following checklist:
Are you https://support.twilio.com/hc/en-us/articles/360025446533-Troubleshooting-Twilio-Elastic-SIP-Trunking-and-SIP-Domain-Calls
Are you (or a caller) hearing the "An application error has occurred” error on your call?
Is an outbound call not connecting?
Does the call log show any Debug Events?
Is your TwiML URL or Application SID responding as intended?
Are you (or a caller) experiencing any audio quality issues?

Related

Twilio: How to continue the <Dial> Action after callee rejects call

This seems like a really simple issue, but I've searched the web and can't find an answer, unfortunately.
We're trying to setup a basic forwarding/voicemail service on Twilio. Our expected behavior is that a caller will call in and be forwarded to 3 different numbers. If none of the numbers answer, the caller is directed to the company voicemail.
Our issue comes in when any of the numbers reject the call (by pressing the red button on their phone) or are set to Do Not Disturb (which seems to act like a rejection). When this happens, the caller is sent directly to the callee's personal voicemail, instead of the company voicemail. I believe this is because Twilio is passed a "in-progress" status even though the call was rejected.
Is there a way to detect when the call is rejected and continue to the "action" part of our Dial? We looked into the Automatic Machine Detection, but am not sure that is the correct route to take, since it would still reveal the callee's personal voicemail until it determined it was a machine.
Thanks for any help! Our simple code is below.
<Response>
<Dial callerId="+1xxx-xxx-xxxx" timeout="15" action="http://twimlets.com/voicemail?Email=email#email.com&Message=https://website.com/Audio.mp3">
<Number>xxx-xxx-xxxx</Number>
<Number>xxx-xxx-xxxx</Number>
<Number>xxx-xxx-xxxx</Number>
</Dial>
</Response> ```
You can take a look at the blog below, which uses Human Detection (alternatives to AMD) to intelligently handle the dialed party's voicemail.
Outsmart Voice Mail with Human Detection Using Keypress Prompts
You cannot use your current approach with parallel forking, since it cannot account for Voicemail.
You will need to build the sequential dialing logic. Below is some Twilio Function code that may be useful, but you will need to adapt it to meet your needs
Main Function (where you point your Twilio Telephone Number to) is shown first:
Replace:
let phoneTreeUrl = "https://YOUR_FUNTION/PATH";
With your unique Function URL and path (this varies for each Twilio customer). Also update the phoneNumbers to be the phone numbers you want to call. You can pass the Timeout as a variable when you call the function from your Twilio phone number or change it in the code below (it defaults to 30 seconds).
Update the PLACE_HOLDER URL with the other Function you will create in the next step further below.
/*
* Example: Strictly Linear Phone Tree
* This example shows how you might iterate through a list of numbers.
* Each will be tried for 10 seconds before moving on to the next.
*/
exports.handler = function(context, event, callback) {
// REQUIRED - URL to this Function
let phoneTreeUrl = "https://YOUR_FUNTION/PATH";
// Timeout - The amount of time we want to dial before giving up
let timeout = event.Timeout || 30;
// Attempt - The position in the list we are currently at
let attempt = parseInt(event.Attempt) || 0;
console.log(attempt);
// DialCallStatus - Returned by <Dial> action
let DialCallStatus = event.DialCallStatus || null;
console.log(DialCallStatus);
// Phone Numbers - The list of numbers to cycle through
let phoneNumbers = [
"+14073601234", "+16787851234"
];​
// generate the TwiML to tell Twilio how to forward this call
let twiml = new Twilio.twiml.VoiceResponse();
// If we have successfully contacted a number, then exit Function
if (DialCallStatus === "completed" || DialCallStatus === "answered") {
twiml.hangup();
callback(null, twiml);
}
// If we have exhausted all numbers end the attempts
if (attempt >= phoneNumbers.length) {
twiml.say("Sorry, we could not find someone to take your call. Please try again later");
callback(null, twiml);
}
// Build the state for our Twiml response
let target = phoneNumbers[attempt];
let nextAttempt = attempt + 1;
let nextAttemptUrl = phoneTreeUrl + "?Attempt=" + nextAttempt;
twiml.dial({ timeout: timeout, action: nextAttemptUrl})
.number({url: "https://PLACE_HOLDER/humandetect?Detection=required"}, target);
callback(null, twiml);
};
Human Detection Function:
Give this new function the path /humandetect
Update the code below, THIS_FUNCTION, to the unique URL for this FUNCTION (with the path of /humandetect)
exports.handler = function(context, event, callback) {
let twiml = new Twilio.twiml.VoiceResponse();
// REQUIRED - URL to this Function
let phoneTreeUrl = "https://THIS_FUNCTION/humandetect";
let detection = event.Detection || null;
if (detection === "required") {
twiml.gather({timeout: 5, numDigits: 1, action: phoneTreeUrl})
.say("Press any key to hear an important message about your appointment.");
twiml.hangup();
}
callback(null, twiml);
};

Ways to subscribe topic data published to mosquitto broker

Device side mqtt publishes data to mosquitto broker installed on Raspberry Pi to a topic.
how to subscribe the data from the mosquitto broker in 2 ways.
Normal google example search gives me code samples. But what i want is 2 ways i thought one is MQTT API to subscribe providing topic which listens every time checking whether data has arrived or not which reduces the CPU performance and speed.
So, Other is if a message has arrived in the topic then it should call back saying message arrived instead of me going and looking into topic everytime checking is cumbersome. The second way increases CPU performance.
MemoryPersistence memoryPersistence = new MemoryPersistence();
MqttConnectOptions conOpt = new MqttConnectOptions();
conOpt.setUserName("mqttuser");
conOpt.setPassword(new String("mqttpassword").toCharArray());
conOpt.setCleanSession(true);
try {
MqttAsyncClient mqttAsyncClient = new MqttAsyncClient("tcp://localhost:1883", "1883", memoryPersistence);
mqttAsyncClient.setCallback(new MqttConnectionCallback());
if (!mqttAsyncClient.isConnected()) {
IMqttToken token = mqttAsyncClient.connect(conOpt);
logger.info();
System.out.println("Connected");
}
} catch (MqttException e) {
e.printStackTrace();
System.out.println("Unable to set up client: "+e.toString());
System.exit(1);
}
this is my listener class overridden method
#Override
public void messageArrived(String topic, MqttMessage msgData) throws Exception {
String time = new Timestamp(System.currentTimeMillis()).toString();
System.out.println("Time:\t" +time +
" Topic:\t" + topic +
" Message:\t" + new String(msgData.getPayload()) +
" QoS:\t" + msgData.getQos());
}
Need some clearance from coding side how this is accompolished in asynchronous ways.
Please correct if my understanding is wrong, specifically on how listener listenes on topicname and how the binding is done.
You need to use the subscribe() method on the mqttAsyncClient object (after connection has completed)
You can call this multiple times to subscribe to multiple topics.
Messages will be delivered to the messageArrived() callback and you can use the topic argument to determine which subscription the message arrived from.

Twilio - Using conference announce to update caller

My question: Can Twilio Announcements be used when there is only a single participant in the conference?
My Test Application: Is a simple node app that keeps a caller waiting while work is done in the background, with periodic updates on progress to the caller, before finally moving the call to a real person.
The problem: I saw Announcements and that this would excellent for my needs.
My node test app successfully dumps each incoming call into its own unique conference. I later attempt to announce an update on the background processing while the caller is waiting.
client.conferences(conferenceSid)
.update({announceUrl:'https://cccbae85.ngrok.io/twilio/announce'})
.then(result => console.log('success'))
.catch(error => console.log('conference error = ' + error));
The following results:
conference error = Error: The requested resource /2010-04-01/Accounts/ACX*/Conferences/CFb15222ac23964077e8161c819cd9dcca.json was not found
When I change this to use a conference AND participant:
client.conferences(conferenceSid)
.participants (particpantCallSid)
.update({announceUrl:'https://cccbae85.ngrok.io/twilio/announce'})
.then(result => console.log('success'))
.catch(error => console.log('conference error = ' + error));
The result is 'success', meaning the conferenceSid was accepted, but I never see any call to the announceUrl (no errors in Twilio, no attempts through ngok).
So back to my question, can Announcements be used in conferences that have a single participant, or do I need to go back to having a "bot" jump into the conference, say something, and jump back out.
OR - did I royally mess up my understanding of Announce....
Thanks!!

Get twilio callback on call screen success and also on failure

I have some working code for call screening with NodeJS, which I modified from the official twilio example.
https://www.twilio.com/docs/howto/callscreening
https://github.com/coolaj86/bizilio/blob/master/routes/twilio/voice/index.js#L246
Snippit:
response += ""
+ '<Response><Gather action="/twilio/voice/connect' + search + '" finishOnKey="any digit" numDigits="1">'
+ '<Say>Press any key to accept this call</Say>'
+ '</Gather>'
// TODO instead of hanging up, redirect to voicemail?
// otherwise it's left to the fallback url to pickup the voicemail and that takes a while
+ '<Hangup/>'
+ '</Response>'
;
If the screening completes successfully, I get a callback to /twilio/voice/connect?foo=bar.
If the screening is unsuccessful I also want a callback to /twilio/voice/miss?foo=bar.
Is the most appropriate way to do this to do a <Redirect> instead of <Hangup/> and then do the <Hangup/> in the redirect? Or should I had a statusCallback somewhere in the original dial and reference the call id?
In thinking about the possibilities to write out the question here, I've probably already discovered a working solution (and I'll go try it), but I'd still like to hear a best practice approach.
As you suggest, you should replace the <Hangup> with a <Redirect>/twilio/voice/miss?foo=bar</Redirect>. After the timeout expires (by default 5 seconds, but configurable via the timeout attribute of the Gather verb), if no input has been received it will go to the next instruction.
From the Twilio Docs for <Gather>:
If no input is received before timeout, falls through to the next verb in the TwiML document.
In the URL that you redirect to you can record that no input was gathered and return any TwiML you like to continue processing the call or return an empty <Response></Response> (or Hangup) to end the call.
StatusCallback is only used at the completion of the call and cannot execute further TwiML instructions.

Worklight: Push Notification message length & formatting - limitations

I am facing below issues when sending Push notifications through Worklight.
Push Message length is very much limited - around 65 characters
payload message when received on device has removed all spacing
like i sent "This is a test message" but on device it received as "Thisisatestmessage"
Now , what is the limited size of Push message in worklight specially , i know Apple says for 256 Bytes. But what Worklight allows?
and why payload is removing spaces. Even i am sending message from a back-end java service
My Push Adapter:
function generalNotification(userId, msgTitle, MsgContents, org, logo){
var userSubscription = WL.Server.getUserNotificationSubscription('aahadPushAdapter.GeneralPushSource', userId);
if (userSubscription==null){
return { result: "No subscription found for user :: " + userId };
}
WL.Logger.debug("Sending Push >> userId:: " + userId + ", Message:: " + MsgContents);
WL.Server.notifyAllDevices(userSubscription, {
badge: 1,
sound: "sound.mp3",
activateButtonLabel: "Read",
alert: msgTitle,
payload: {
msg : MsgContents,o:org,l:logo
}
});
return { result: "Notification sent to user :: " + userId };
}
my back-end Java code:
DataAccessService service = WorklightBundles.getInstance().getDataAccessService();
String parm = "['" + userID + "','"+ msgTitle + "','"+ msgContents+ "','"+org + "','"+logo +"']";
ProcedureQName pushMethod = new ProcedureQName("aahadPushAdapter","transNotification");
InvocationResult results = service.invokeProcedure(pushMethod, parm);
jsonObj = results.toJSON();
msg = "Push Sent successfully to " + userID + " " + (String)jsonObj.get("");
Please check this code and suggest , if something is missing here?
thanks
Does the stripping of spaces also happen in the Push Notifications sample application provided in the IBM Worklight Getting Started training material? Because for me, it doesn't.
If it happens only in your application, need to understand how you're processing the message.
As I have mentioned to you in a comment elsewhere, Worklight does not place any restrictions - each PNS (APNS, MSPN, GCM) has its own limitation.
The 256 bytes are not only for the message part of the payload, but for the entirety of the payload, so it could be that for the message part what is left is only 65 characters, but again, this is not in Worklight's control.
I haven't done this yet myself, but you can start stripping the payload and see when it fails, that would be your minimum payload from Worklight's perspective.
The message is not meant to be long in principle.
Another way to maybe increase what you can pass in the message (in the remaining size of the payload) is to use an alias so that less information is passed, thus more space remains for the message.
The stripping of spaces in APNS payload appears to be a defect. I seen the same behavior in my application and was able to reproduce it in the getting started materials. As a workaround I put "_" in the payload as a placeholder for spaces and then removed them in the worklight client.

Resources