Nexmo Voice API - connect two users and play a different talk action to each user - json

I'm making an outbound call to a customer using POST https://api.nexmo.com/v1/calls/.
I pass in this NCCO which plays the talk Hello customer, please wait while we connect you to the customer and connects to a salesperson (SALESPERSON_PHONE_NUMBER).
What I want to do is play a different talk to the salesperson only when they answer, something like outbound call to customer for Example Company
[
{
"action": "talk",
"text": "Hello customer, please wait while we connect you."
},
{
"action": "connect",
"timeout": 20,
"from": "MY_NEXMO_PHONE_NUMBER",
"endpoint": [
{
"type": "phone",
"number": "SALESPERSON_PHONE_NUMBER"
}
]
}
]
How can I play a different talk message to the salesperson only? I could not see anything in the documentation.

The connect NCCO action has an onAnswer option. From the documentation:
onAnswer - A JSON object containing a required url key. The URL serves an NCCO to execute in the number being connected to, before that call is joined to your existing conversation. Optionally, the ringbackTone key can be specified with a URL value that points to a ringbackTone to be played back on repeat to the caller, so they do not hear just silence. The ringbackTone will automatically stop playing when the call is fully connected. Example: {"url":"https://example.com/answer", "ringbackTone":"http://example.com/ringbackTone.wav" }. Please note, the key ringback is still supported.
So if you change your NCCO to look something like this, the salesperson will hear the talk action in the second NCCO, while the caller hears music.
[
{
"action": "talk",
"text": "Hello customer, please wait while we connect you."
},
{
"action": "connect",
"timeout": 20,
"from": "MY_NEXMO_PHONE_NUMBER",
"endpoint": [
{
"type": "phone",
"number": "SALESPERSON_PHONE_NUMBER",
"onAnswer": {
"url":"https://example.com/answer",
"ringbackTone":"http://example.com/ringbackTone.wav"
}
}
]
}
]
https://example.com/answer should be
[{
"action": "talk",
"text": "Hello salesperson, please wait while we connect you."
}]

It looks like you want to use the onAnswer functionality in the connect action
https://developer.nexmo.com/voice/voice-api/ncco-reference#connect
A JSON object containing a required url key. The URL serves an NCCO to execute in the number being connected to, before that call is joined to your existing conversation.
[
{
"action": "talk",
"text": "Hello customer, please wait while we connect you."
},
{
"action": "connect",
"timeout": 20,
"from": "MY_NEXMO_PHONE_NUMBER",
"endpoint": [
{
"type": "phone",
"number": "SALESPERSON_PHONE_NUMBER",
"onAnswer": {"url": "https://example.com/my-on-answer-ncco"}
}
]
}
]
Then at https://example.com/my-on-answer-ncco, you return an NCCO containing a talk action

Related

Cloudwatch Logs Insights aggregating data for application dashboard

I have a lambda function that makes a call to a ticketing API, and returns a list of tickets and their attributes (open/resolved, assignee, etc). I want to build a dashboard within CloudWatch to show this information but I'm not sure if I'm approaching the problem correctly.
For example if I wanted a visualization of "Open tickets which are assigned to Jason" which changes over time. I've tried using Log Insights, but the response message is an array of tickets, which I've not been able to successfully query. The logs are structured as:
{
"level": "INFO",
"location": "get_all_tickets:18",
"message": [
{
"ticketId": "001",
"status": "Open",
"assignee": "Jason",
"requester": "Paul",
"createdAt": "2022-10-20 11:08:35.105000+00:00",
"lastUpdatedAt": "2022-10-25 13:42:52.881000+00:00",
"title": "Example Ticket 1",
},
{
"ticketId": "002",
"status": "Resolved",
"assignee": "Jason",
"requester": "John",
"createdAt": "2022-10-20 11:09:35.105000+00:00",
"lastUpdatedAt": "2022-10-25 13:42:52.881000+00:00",
"title": "Example Ticket 2",
}
],
"timestamp": "2022-10-27 18:26:32,680+0000",
"service": "ticket_metrics"
}
Within Logs Insights the fields are serialized as message.0.status, message.1.status, etc, but I haven't found a way to query and aggregate these. Is there a way I can produce a metric, like the above example "Open Tickets assigned to Jason" from within Logs Insights?
I tried queries from the Logs Insights docs, but these didn't perform as expected or didn't apply to my use case.

Amadeus flights API error: carrier code is a 2 or 3 alphanum except YY and YYY

I am using the following SDK to search for and purchase flights via Amadeus:
https://github.com/autotune/amadeus/pull/1/files
This was a previously abandoned project I have decided to take on and make work. As part of that project I am trying to purchase a ticket in the sandbox environment and getting the following error:
{
"errors": [
{
"code": 477,
"title": "INVALID FORMAT",
"detail": "carrier code is a 2 or 3 alphanum except YY and YYY",
"source": {
"pointer": "/data/flightOffers[0]/itineraries[1]/segments[0]/operating/carrierCode",
"example": "AF"
},
"status": 400
}
]
}
Here is the json data being sent:
{
"type": "flight-order",
"travelers": [
{
"id": "1",
"dateOfBirth": "1990-02-15",
"name": {
"firstName": "Foo",
"lastName": "Bar"
},
"gender": "MALE",
"contact": {
"emailAddress": "foo#bar.com",
"phones": [
{
"deviceType": "MOBILE",
"countryCallingCode": "33",
"number": "5555555555"
}
]
}
}
],
"ticketingAgreement": {
"option": "DELAY_TO_CANCEL",
"delay": "6D"
},
"remarks": {},
"operating": {
"carrierCode": "UA"
}
}
Any help appreciated!
The error suggests that the sent payload is invalid. I'd advice you use a tool like Curl or Postman to verify you're using the right API documentation, before debugging actual code.
After further reading your PR and checking the API reference at :
https://developers.amadeus.com/self-service/category/air/api-doc/flight-create-orders/api-reference
I think you need to confirm that the Carrier code being passed is available in the segments under:
flightOffers > itineraries > segments
Although the API reference doesn't have operating > carrierCode like you used in the data sent, my guess after seeing the API error response you shared is that they are performing a check against the flight offers passed.
I suggest you check the results gotten when you call the flightOffers and also add it to the payload sent to the sandbox.

FIWARE - Orion Context Broker as Context Provider

I'm having a hard time understanding how context providers work in the Orion Context Broker.
I followed the examples in the step-by-step guide written by Jason Fox. However, I still do not exactly get what happens in the background and how the context broker exactly creates the POST from the registration. Here is what I am trying to do:
I do have a WeatherStation that provides sensor data for a neighborhood.
{
"id": "urn:ngsi-ld:WeatherStation:001",
"type": "Device:WeatherStation",
"temperature": {
"type": "Number",
"value": 20.5,
"metadata": {}
},
"windspeed": {
"type": "Number",
"value": 60.0,
"metadata": {}
}
}
Now I like the WeatherStation to be a context provider for all buildings.
{
"id": "urn:ngsi-ld:building:001",
"type": "Building"
}
Here is the registration that I try to use.
{
"id": null,
"description": "Random Weather Conditions",
"provider": {
"http": {
"url": "http://localhost:1026/v2"
},
"supportedForwardingMode": "all"
},
"dataProvided": {
"entities": [
{
"id": "null",
"idPattern": ".*",
"type": "Building",
"typePattern": null
}
],
"attrs": [
"temperature",
"windspeed"
],
"expression": null
},
"status": "active",
"expires": null,
"forwardingInformation": null
}
The context broker accepts both entities and the registration without any error.
Since I have a multi-tenant setup I use one fiware_service for the complete neighborhood but every building would later have a seperate fiware_servicepath. Hence, the weatherstation has a different servicepath than the building. Although I also tried to put them both on the same path.
For now I used the same headers for all entities.
{
"fiware-service": "filip",
"fiware-servicepath": "/testing"
}
Here is the log of the context broker (version: 3.1.0):
INFO#2021-09-23T19:17:17.944Z logTracing.cpp[212]: Request forwarded (regId: 614cd2b511c25270060d873a): POST http://localhost:1026/v2/op/query, request payload (87 bytes): {"entities":[{"idPattern":".*","type":"Building"}],"attrs":["temperature","windspeed"]}, response payload (2 bytes): [], response code: 200
INFO#2021-09-23T19:17:17.944Z logTracing.cpp[130]: Request received: POST /v2/op/query?options=normalized%2Ccount&limit=1000, request payload (55 bytes): {"entities": [{"idPattern": ".*", "type": "Building"}]}, response code: 200
The log says that it receives the request and forwards it as expected. However, as I understand it this would simply point to the same building entity again. Hence, it is somehow a circular forwarding. I also cannot tell anything about the headers of the request.
I do not understand how the forwarded request from the building can actually query the weather station for information. When I query my building I still only receive the entity with no own properties:
{
"id": "urn:ngsi-ld:building:001",
"type": "Building"
}
I also tried to vary the url of the registration but with no success.
Is this scenario actually possible with the current implementation? It would be very useful
Is there any example for this including also the headers?
I know that I could simply use reference but that would put more work on the user.
Thanks for any help on this.
It is messy, but you could achieve this via a subscription. Hold the weather station as a separate entity in the context broker and poll or push updates into the entity. The subscription would fire whenever the data changes and make two NGSI requests:
Find all entities which have a Relationship servicedBy=WeatherStationX
Run an upsert on all entities to add a Property to each entity:
{
"temperature" : {
"type" : "Property",
"value" : 7,
"unitCode": "CEL",
"observedAt": "XXXXX",
"providedBy": "WeatherStation1"
}
}
Where observedAt comes either from the payload of the weather station or the notification timestamp.
Within the existing IoT Agents, provisioning the link attribute allows a device to propagate measures to a second entity (e.g. this Thermometer entity is measuring temperature for an associated Building entity)
{
"entity_type": "Device",
"resource": "/iot/d",
"protocol": "PDI-IoTA-UltraLight",
..etc
"attributes": [
{"object_id": "l", "name": "temperature", "type":"Float",
"metadata":{
"unitCode":{"type": "Text", "value" :"CEL"}
}
}
],
"static_attributes": [
{
"name": "controlledAsset",
"type": "Relationship",
"value": "urn:ngsi-ld:Building:001",
"link": {
"attributes": ["temperature"],
"name": "providedBy",
"type": "Building"
}
}
]
}
At the moment the logic just links direct one-to-one, but it would be possible to raise a PR to check for an Array and update multiple entities in an upsert - the relevant section of code is here

How to check if name already exists? Azure Ressource Manager Template

is it possible to check, in an ARM Template, if the name for my Virtual Machine already exists?
I am developing a Solution Template for the Azure Marketplace. Maybe it is possible to set a paramter in the UiDefinition uniqe?
The goal is to reproduce this green Hook
A couple notes...
VM Names only need to be unique within a resourceGroup, not within the subscription
Solution Templates must be deployed to empty resourceGroups, so collisions with existing resources aren't possible
For solution templates the preference is that you simply name the VMs for the user, rather than asking - use something that is appropriate for the workload (e.g. jumpbox) - not all solutions do this but we're trying to improve that experience
Given that it's not likely we'll ever build a control that checks for naming collisions on resources without globally unique constraints.
That help?
This looks impossible, according to the documentation.
There are no validation scenarious.
I assume that you should be using the Microsoft.Common.TextBox UI element in your createUiDefinition.json.
I have tried to reproduce a green check by creating a simple createUiDefinition.json as below with a Microsoft.Common.TextBox UI element as shown below.
{
"$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json",
"handler": "Microsoft.Compute.MultiVm",
"version": "0.1.2-preview",
"parameters": {
"basics": [
{
"name": "textBoxA",
"type": "Microsoft.Common.TextBox",
"label": "VM Name",
"defaultValue": "",
"toolTip": "Please enter a VM name",
"constraints": {
"required": true
},
"visible": true
}
],
"steps": [],
"outputs": {}
}
}
I am able to reproduce the green check beside the VM Name textbox as shown below:
However, this green check DOES NOT imply the VM Name is Available.
This is because based on my testing, even if I use an existing VM Name in the same subscription, it is still showing the green check.
Based on the official documented constraints that are supported by the Microsoft.Common.TextBox UI element, it DOES NOT VALIDATE Name Availability.
Hope this helps!
While bmoore's point is correct that it's unlikely you would ever need this for a VM (nor is there an API for it), there are other compute resources that do have global naming requirements.
As of 2022 this concept is possible now with the use of the ArmApiControl UI element. It allows you to call ARM apis as part of validation in the createUiDefinition.json. Here is an example using the check name API for an Azure App service.
{
"$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#",
"handler": "Microsoft.Azure.CreateUIDef",
"version": "0.1.2-preview",
"parameters": {
"basics": [
{}
],
"steps": [
{
"name": "domain",
"label": "Domain Names",
"elements": [
{
"name": "domainInfo",
"type": "Microsoft.Common.InfoBox",
"visible": true,
"options": {
"icon": "Info",
"text": "Pick the domain name that you want to use for your app."
}
},
{
"name": "appServiceAvailabilityApi",
"type": "Microsoft.Solutions.ArmApiControl",
"request": {
"method": "POST",
"path": "[concat(subscription().id, '/providers/Microsoft.Web/checknameavailability?api-version=2021-02-01')]",
"body": "[parse(concat('{\"name\":\"', concat('', steps('domain').domainName), '\", \"type\": \"Microsoft.Web/sites\"}'))]"
}
},
{
"name": "domainName",
"type": "Microsoft.Common.TextBox",
"label": "Domain Name Word",
"toolTip": "The name of your app service",
"placeholder": "yourcompanyname",
"constraints": {
"validations": [
{
"regex": "^[a-zA-Z0-9]{4,30}$",
"message": "Alphanumeric, between 4 and 30 characters."
},
{
"isValid": "[not(equals(steps('domain').appServiceAvailabilityApi.nameAvailable, false))]",
"message": "[concat('Error with the url: ', steps('domain').domainName, '. Reason: ', steps('domain').appServiceAvailabilityApi.reason)]"
},
{
"isValid": "[greater(length(steps('domain').domainName), 4)]",
"message": "The unique domain suffix should be longer than 4 characters."
},
{
"isValid": "[less(length(steps('domain').domainName), 30)]",
"message": "The unique domain suffix should be shorter than 30 characters."
}
]
}
},
{
"name": "section1",
"type": "Microsoft.Common.Section",
"label": "URLs to be created:",
"elements": [
{
"name": "domainExamplePortal",
"type": "Microsoft.Common.TextBlock",
"visible": true,
"options": {
"text": "[concat('https://', steps('domain').domainName, '.azurewebsites.net - The main app service URL')]"
}
}
],
"visible": true
}
]
}
],
"outputs": {
"desiredDomainName": "[steps('domain').domainName]"
}
}
}
You can copy the above code and test it in the createUiDefinition.json sandbox azure provides.

Data Factory: AzureSQL in- and output for pipeline activity type AzureMLBatchExecution

In Azure Data Factory, I’m trying to call an Azure Machine Learning model by a Data Factory Pipeline. I want to use a Azure SQL table as input and another Azure SQL table for the output.
First I deployed a Machine Learning (classic) web service. Then I created an Azure Data Factory Pipeline, using a LinkedService (type= ‘AzureML’, using Request URI and API key of the ML-webservice) and a input and output dataset (‘AzureSqlTable’ type).
Deploying and Provisioning is succeeded. The pipeline starts as scheduled, but keeps ‘Running’ without any result. The pipeline activity is not being shown in the Monitor&Manage: Activity Windows.
On different sites and tutorials, I only find JSON-scripts using the activity type ‘AzureMLBatchExecution’ with BLOB in- and outputs. I want to use AzureSQL in- and output but I can’t get this working.
Can someone provide a sample JSON-script or tell me what’s possibly wrong with the code below?
Thanks!
{
"name": "Predictive_ML_Pipeline",
"properties": {
"description": "use MyAzureML model",
"activities": [
{
"type": "AzureMLBatchExecution",
"typeProperties": {},
"inputs": [
{
"name": "AzureSQLDataset_ML_Input"
}
],
"outputs": [
{
"name": "AzureSQLDataset_ML_Output"
}
],
"policy": {
"timeout": "02:00:00",
"concurrency": 3,
"executionPriorityOrder": "NewestFirst",
"retry": 1
},
"scheduler": {
"frequency": "Week",
"interval": 1
},
"name": "My_ML_Activity",
"description": "prediction analysis on ML batch input",
"linkedServiceName": "AzureMLLinkedService"
}
],
"start": "2017-04-04T09:00:00Z",
"end": "2017-04-04T18:00:00Z",
"isPaused": false,
"hubName": "myml_hub",
"pipelineMode": "Scheduled"
}
}
With a little help from a Microsoft technician, I've got this working. The JSON script as mentioned above is only changed in the schedule-section:
"start": "2017-04-01T08:45:00Z",
"end": "2017-04-09T18:00:00Z",
A pipeline is active only between its start time and end time. Because the scheduler is set to weekly, the pipeline is triggered at the start of the week: that date should be within start- and end date. For more details about scheduling, see: https://learn.microsoft.com/en-us/azure/data-factory/data-factory-scheduling-and-execution
The Azure SQL Input dataset should look like this:
{
"name": "AzureSQLDataset_ML_Input",
"properties": {
"published": false,
"type": "AzureSqlTable",
"linkedServiceName": "SRC_SQL_Azure",
"typeProperties": {
"tableName": "dbo.Azure_ML_Input"
},
"availability": {
"frequency": "Week",
"interval": 1
},
"external": true,
"policy": {
"externalData": {
"retryInterval": "00:01:00",
"retryTimeout": "00:10:00",
"maximumRetry": 3
}
}
}
I added the external and policy properties to this dataset (see script above) and after that, it worked.