How do we post messages to event grid topics? - json

I have created event grid topic in azure using event schema = "Event Grid Schema".
The next steps for me is trying to send messages to that event grid topic so the subscribers can do something when the message has been successfully received in event grid topic.
However, I had a problem when sending the message to event grid topic. It always reject my JSON request with error "Required property 'subject' was not set. even tough, I have explicitly set the subject in my JSON post body.
I have also add 'aeg-sas-key' value in header for authentication purposes.
Here is an example of my JSON format:
{
"id": "19291",
"subject": "myapp/vehicles/motorcycles",
"topic": "VehicleData",
"eventType": "statusupdated",
"eventTime": "2019-05-12T18:41:00.9584103Z",
"data":{
"firstName": "Jason",
"postalAddress": "xyz"
},
"dataVersion": "1.0",
"metadataVersion": "string"
}
and Here is the output:
{
"error": {
"code": "BadRequest",
"message": "Required property 'subject' was not set. Report '433759ee-6570-466e-ae12-a6dc5fccbfe1:5/14/2019 4:01:32 AM (UTC)' to our forums for assistance or raise a support ticket.",
"details": [
{
"code": "InputJsonInvalid",
"message": "Required property 'subject' was not set. Report '433759ee-6570-466e-ae12-a6dc5fccbfe1:5/14/2019 4:01:32 AM (UTC)' to our forums for assistance or raise a support ticket."
}
]
}
}
Any idea why it always ask for subject even tough I have provided the subject in my JSON?

Based on the docs:
Post to custom topic for Azure Event Grid
Azure Event Grid event schema
use the following payload:
[
{
"id": "19291",
"subject": "myapp/vehicles/motorcycles",
"topic": null,
"eventType": "statusupdated",
"eventTime": "2019-05-12T18:41:00.9584103Z",
"data": {
"firstName": "Jason",
"postalAddress": "xyz"
},
"dataVersion": "1.0",
"metadataVersion": null
}
]

If you created the topic using the Azure Portal, did you somewhere specify the inputSchemaMapping?
According to the specifications here: https://learn.microsoft.com/en-us/rest/api/eventgrid/topics/createorupdate
You need to specify a inputSchemaMapping when opting for the CustomEventSchema.

Related

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

In MS Team Adaptive Card, how do I specify the server it post to?

I am trying to use Action.Submit in my adaptive card to hit my Google Cloud Function. Where do I specify where to send the submission to? The reason I am doing this is I want to skip building a full chat server due to time constraint.
Example of Adaptive Card, no property to specify post URL:
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "TextBlock",
"text": "Present a form and submit it back to the originator"
},
{
"type": "Input.Text",
"id": "firstName",
"placeholder": "What is your first name?"
},
{
"type": "Input.Text",
"id": "lastName",
"placeholder": "What is your last name?"
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Action.Submit",
"data": {
"x": 13
}
}
]
}
Adaptive cards aren't developed specifically for bot service.
so working with them needs some tricks , in your case if you are trying to send a request that contain adaptive card inputs you need to know :
when the user click the submit button the adaptive card will send a message to bot activity handler on behalf of the user, this message contains a JSON object (you can view this object by adding this line in the bot onMessage function.
console.log(context.activity)
you can get the data from this meesage by using :
context.activity.value.firstName (to get the firstName sent by the adaptive card)
Now you can send your request to the server i prefer using Axios .

Why can't I submit a record to Zoho Sales Order API?

I'm trying to insert a record using the Zoho API, and I keep receiving a cryptic INVALID_DATA error message.
I've tried using their sample code which, of course, produces another error. And the sample code they provide for running in Postman also produces an error.
Their docs are lacking and inconsistent, and nobody is getting back to me on their message boards, and I'm getting desperate as I need to have this done today. Can anyone see what I'm doing wrong?
This is what I'm submitting via Postman
{
"data": [
{
"Owner": {
"id": "3938209039489388001"
},
"Contact_Name": {
"id": "398129039938498309"
},
"Subject": "Test",
"Product_Details": [
{
"product": {
"id": "1234567"
},
"quantity": 1
}
]
}
]
}
This is the error response
{
"data": [
{
"code": "INVALID_DATA",
"details": {
"api_name": "product",
"index": 0,
"parent_api_name": "Product_Details"
},
"message": "invalid data",
"status": "error"
}
]
}
The solution was to POST a product first, then grab that product ID and insert it under Product_Details. This is not documented, so I assumed the product would be created automatically, which it wasn't.

Best Practice Design typed JSON Objects

Currently we are designing a System that will send JSON Objects to registered consumers. The consumers will be able to register for different Object Types that they want to receive. Currently we are designing the JSON Objects that will be consumed by the registered consumers.
As we see there are two possible approaches to define typed JSON Objects.
A generic JSON Object that has some properties set or it has them not set:
{
"timestamp": 1589448935,
"customer_id": "123123123123",
"message": {
"title": "Desired Title",
"text": "The Text of the Message",
}
}
{
"timestamp": 1589448935,
"customer_id": "123123123123",
"message": {
"title": "Desired Title",
"text": "The Text of the Message",
"avatar": "http://avatar.io/avatar"
}
}
A Type field on each JSON Object that specifies which Type this object is from:
{
"timestamp": 1589448935,
"customer_id": "123123123123",
"type": "simple_message",
"message": {
"title": "Title",
"text": "Message",
}
}
{
"timestamp": 1589448935,
"customer_id": "123123123123",
"type": "avatar_message",
"message": {
"title": "Title",
"text": "Message",
"avatar": "http://www.avatar.io/avatar"
}
}
From our point of view a more generic approach would be easier to handle within our system, because we would not need to handle multiple types, we just can append a property or leave it away.
From point of view of a developer I could imagine that a type field could help the developer when handling such objects (f.e. mapping them to objects) or switch on the type field to execute some specific logic.
Finally, to my question - which style is the one to be preferred (best-practice) when we want to make the life for consumers as easy as possible and why? Is there a best-practice approach for typed json objects?
If you are set on a generic application/json response then I would go with your option #2.
That "type" doesn't hurt and can only help clarify what that response is.

OneNote API Get Notebooks issue

The following is a sample schema from the OneNote API documentation at this site and will can be used with json2csharp.com with no problems.
http://dev.onenote.com/docs#/reference/get-notebooks.
{
"createdBy": "user name",
"createdTime": "2013-10-05T10:57:00.683Z",
"id": "notebook ID",
"isDefault": false,
"isShared": false,
"lastModifiedBy": "user name",
"lastModifiedTime": "2014-01-28T18:49:00.47Z",
"links": {
"oneNoteClientUrl": {
"href": "onenote:https://{client URL}"
},
"oneNoteWebUrl": {
"href": "https://{web URL}"
}
},
"name": "notebook name",
"sectionGroupsUrl": "https://www.onenote.com/api/v1.0/notebooks/{notebook ID}/sectionGroups",
"sectionsUrl": "https://www.onenote.com/api/v1.0/notebooks/{notebook ID}/sections",
"self": "https://www.onenote.com/api/v1.0/notebooks/{notebook ID}",
"userRole": "Contributor"
}
However, using the following Get Notebooks link has a different schema that doe
sn't pass json2csharp. Parsing your JSON didn't work. Please make sure it's valid.
"https://graph.microsoft.com/v1.0/me/onenote/notebooks"
createdBy and lastmodifiedBy are thrown as exceptions.
The sample from the apigee.com/console app uses the https://www.onenote.com/api/v1.0/me/notes/notebooks link and has the correct schema.
How do I resolve this discrepancy? Or am I mistaken?
The response payload returned from the Microsoft Graph API is slightly different from the response payload returned from the OneNote API directly.
Here's a reference to the notebook properties returned from Microsoft Graph: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/notebook
And this is what gets returned from the OneNote API directly:
https://msdn.microsoft.com/en-us/library/office/dn769050.aspx => Response properties