I want to publish a message to IoT Hub and also receive the message via the same topic. I connected to IoT Hub and then subscribed to the same topic to which i send the messages, but I don't receive any message. As Client I am using MQTTX windows. Messages are sent and received correctly at the cloud endpoint (telemetry data). Here is a screenshot from my MQTT client: MQTT Client
I see you are using MQTTX as a leaf device to IoT Edge in a transparent gateway pattern, where edge will just pass through messages to IoTHub.
IoTHub does not support custom topic or respond back on the same topic so this "devices/plc2/messages/events/topic" will not work
Subscription to devices/{device_id}/messages/devicebound/# will work but you will need to explicitly send C2D message for that device_id as a response
The Azure IoT Hub is not a generic MQTT broker, see more details here.
I do recommend to read also the doc for Azure IoT Edge MQTT broker.
UPDATE:
Based on your needs, such as a round trip time test, the following is an example how can be achieved this loopback in the Azure IoT Central. Note, that the Iot Central App has a built-in great features to simplify your test without using additional azure resource such as an Azure function.
The concept of this example is based on the following:
REST API for invoking a durable command (Queuing command) to generate a C2D Message.
Using the Data Transformation for exporting a message to the webhook destination
First of all, we have to create a device template (in my example loopback) for our test:
{
"#id": "dtmi:rk2022iotcfree:loopback_24v;1",
"#type": "Interface",
"contents": [
{
"#id": "dtmi:rk2022iotcfree:loopback_24v:message;1",
"#type": "Command",
"displayName": {
"en": "Message"
},
"name": "message",
"request": {
"#type": "CommandPayload",
"displayName": {
"en": "Info"
},
"name": "Info",
"schema": {
"#type": "Object",
"displayName": {
"en": "Object"
},
"fields": [
{
"displayName": {
"en": "ts"
},
"name": "ts",
"schema": "dateTime"
},
{
"displayName": {
"en": "msg"
},
"name": "msg",
"schema": "string"
}
]
}
},
"durable": true
},
{
"#id": "dtmi:rk2022iotcfree:loopback_24v:counter;1",
"#type": "Telemetry",
"displayName": {
"en": "Counter"
},
"name": "counter",
"schema": "double"
},
{
"#id": "dtmi:rk2022iotcfree:loopback_24v:time;1",
"#type": "Telemetry",
"displayName": {
"en": "Timestamp"
},
"name": "time",
"schema": "double"
}
],
"displayName": {
"en": "loopback"
},
"#context": [
"dtmi:iotcentral:context;2",
"dtmi:dtdl:context;2"
]
}
Once we have the device template, we can create a device (in my example device1) with assigning to this device template (loopback).
Now, we need to declare a destination webhook endpoint:
where the Callback URL is:
https://2a92220d-42e3-4a73-b700-2cb858c9c5e7.azureiotcentral.com/api/devices/device1/commands/message?api-version=1.2-preview
and the Authorization token is generated as the IoT Central Api token
Next step is declaring a Data transformation for this destination endpoint:
import "iotc" as iotc;
if .device.id == "device1" then
{
request: {
Info:{
ts:.enqueuedTime,
msg:("Feedback from device: id=" + .device.id + ", counter=" + (.telemetry | iotc::find(.name == "counter").value | tostring) + ", time=" + (.telemetry | iotc::find(.name == "time").value | tostring))
}
}
}
else
empty
end
That's all at the IoT Central App. Based on the above Data transformation, any received telemetry data message from the device1 is exported to the webhook endpoint for invoking a C2D message.
In my example, for the device side is used my tool for virtual MQTT device (either the Azure IoT Hub Tester or Azure IoT Central Tester), but it can be used any other similar tool or MQTT client.
As you can see the above screen snippet, the device1 sent the telemetry data such as a counter and time and the device received the C2D message:
As the above screen snippet shows, there are three timestamps. The two highlighted timestamps are represented a round trip time (from the device to the IoT Central and back to the device). The third one is represented a timestamp at the IoT Central app:
Start device: 2022-05-19T13:50:06.4213024Z
IoT Central App: 2022-05-19T13:50:07.107Z
End device: 2022-05-19T13:50:13.6934397Z
Related
I am using GoogleFit Rest API to create a nutrition data source so that I can subsequently store nutrition information. I have done this successfully on Android via the GoogleFit SDK, but because no such SDK is available on iOS, I resorted to using the REST APIs via the link above. When trying to create the data source I am returned the following error:
{
"error": {
"code": 403,
"message": "The caller does not have permission",
"errors": [
{
"message": "The caller does not have permission",
"domain": "global",
"reason": "forbidden"
}
],
"status": "PERMISSION_DENIED"
}
}
and the POST request I am using is:
Endpoint: https://www.googleapis.com/fitness/v1/users/me/dataSources
Body:
{
"application": {
"detailsUrl": "https://strongfoundation.dev",
"name": "Strong Foundation",
"packageName": "com.coding.casa.Strong.Foundation",
"version": "1.0.1"
},
"dataStreamId": "raw:com.google.nutrition:com.coding.casa.Strong.Foundation:Apple:iPad Air (3rd generation):****",
"dataType": {
"name": "com.google.nutrition"
},
"device": {
"manufacturer": "Apple",
"model": "iPad Air (3rd generation)",
"type": "phone",
"uid": "*****",
"version": "15.7"
},
"name": "strong-foundation-food",
"type": "raw"
}
Has anyone seen this error and was able to resolve it? I have tried adding the API Key to the request, but that did not change the error, and I do have the Fitness API enabled on my project.
EDIT:
I am also supplying a Bearer token with the following authorized scopes
"https://www.googleapis.com/auth/fitness.activity.read",
"https://www.googleapis.com/auth/fitness.body.write",
"https://www.googleapis.com/auth/fitness.body.read",
"https://www.googleapis.com/auth/fitness.nutrition.read",
"https://www.googleapis.com/auth/fitness.nutrition.write",
You don't include the others details of the REST method call.
Importantly, HTTP 403 is Forbidden suggesting that you didn't include an Authorization header in your request with value Bearer {TOKEN} where {TOKEN} is an access token for an identity that has suitable scopes to access the API. See authorization
Although Swift is not one of Google's officially supported languages, Google has a Swift REST Client Generator for Google APIs and you should be able to use it to generate a Google client library for Swift for Google Fit.
Did some more playing around with the FitnessAPI (specifically creating data sources) and found the issues was with my request payload.
The payload that worked for me is as follows:
{
"application": {
"detailsUrl": "https://strongfoundation.dev",
"name": "Strong Foundation",
"version": "1.0.1"
},
"dataType": {
"name": "com.google.nutrition"
},
"device": {
"manufacturer": "Apple",
"model": "iPad Air (3rd generation)",
"type": "phone",
"uid": "****",
"version": "15.7"
},
"name": "strong-foundation-food",
"type": "raw"
}
The deltas from the original one are removed the following properties:
application.packageName
dataStreamId
We already have GCM/FCM setup up and we are able to send notifications to both iOS and Android devices.
More specifically data-only notifications where we add the parameters ( priority, content_available, collapse_key )
Especially the content_available parameter is crucial when the phone is an iOS device and in order to receive the data-only notifications when the app is in the background. But behaviour seems to be different between https://fcm.googleapis.com/fcm/send call and Portal -> Azure Notification Hub -> Test Send ( or SendFcmNativeNotificationAsync )
Working Case
Everything works as expected when I use the https://fcm.googleapis.com/fcm/send call.
So we have the following message for example:
{
"to": "…REDACTED_THE_ID...",
"collapse_key" : "123456769",
"priority": "high",
"content_available":true,
"time_to_live": 600,
"data": {
"content": {
"id": "9d2b0228-4d0d-4c23-8b49-01a698857710"
},
"dataType": "terminal"
}
}
Issue To Reproduce
But when we use the following message in the Portal -> Azure Notification Hub -> Test Send
Platforms "Android" ( which uses the same Google GCM API Key )
Remove the “to” entry as I am using the "Send To Tag" expression
Azure Notifications hub approves the message and confirms that message was successfully sent.
But then nothing arrives on the iOS smartphone, it seems as if the content_available parameter is not taken into account.
If I add a valid “notification” field (which makes it a NON- data-only notifications ) then it arrives.
{
"collapse_key" : "123456769",
"priority": "high",
"content_available":true,
"time_to_live": 600,
"data": {
"content": {
"id": "9d2b0228-4d0d-4c23-8b49-01a698857710"
},
"dataType": "terminal"
}
}
I am working with below MS Graph API.
POST https://graph.microsoft.com/beta/teams/7155e3c8-175e-4311-97ef-572edc3aa3db/sendActivityNotification
Content-Type: application/json
{
"topic": {
"source": "text",
"value": "Weekly Virtual Social",
"webUrl": "Teams webUrl"
},
"previewText": {
"content": "It will be fun!"
},
"activityType": "eventCreated",
"recipient": {
"#odata.type": "microsoft.graph.channelMembersNotificationRecipient",
"teamId": "7155e3c8-175e-4311-97ef-572edc3aa3db",
"channelId": "19:0ea5de04de4743bcb4cd20cb99235d99#thread.tacv2"
}
}
Documentation here https://learn.microsoft.com/en-us/graph/teams-send-activityfeednotifications
I am successfully able to run the API for my bot application in Teams Desktop APP - meaning the notifications created by the app are visible in the activity feed in the MS desktop app.
But the same notifications are not seen in the mobile app of MS Teams for both Android and iOS.
To be noted: I can see the push notification on the iOS but if click on the banner it opens up the Teams App but that particular notification is not present there.
Is that the limitation from the API or something else that needed to be configured?
The behaviour is quite strange here, If the payload has a topic like below that is "source": "text" will show the push notifications but not in the feed.
"topic": {
"source": "text",
"value": "Weekly Virtual Social",
"webUrl": "Teams webUrl"
},
But, after updating the topic like below source: 'entityUrl' works and show the notifications in the feed.
topic: {
source: 'entityUrl',
value: `https://graph.microsoft.com/v1.0/teams/...../`,
},
Just a note, if one wants to link the notification to a certain message - meaning if you click the notification it'll take to that particular message. Use the below value.
https://graph.microsoft.com/v1.0/teams/${team_id}/channels/${channel_id}/messages/${reply_to_id}
I've upgraded to Cloud Endpoints 2.0 which no longer supports RPC. Therefore, I generated a new discovery document and used the service generator with the REST discovery doc as input in order to generate the client library for my iOS app.
Using the new REST discovery doc I am getting the following error when trying to generate the library:
~/workspace/google-api-objectivec-client-for-rest/Source/Tools/ServiceGenerator/build/Release/ServiceGenerator discovery/servUsApi-v1-rest.discovery --outputDir GTLAPI --gtlrFrameworkName GoogleAPIClientForREST
ERROR: Failure, exception: Looking at parameter 'creditKickbackKash:creditAmount', found a type/format pair of 'number/(null)', and don't how to map that to Objective-C
I was able to manually fix this by adding (in numerous places) in the discovery doc, the "format": "double" key and value for all double parameters. Notice creditAmount below is missing a format, like all other doubles.
The generated discovery doc looks like this:
"creditKickbackKash": {
"httpMethod": "PUT",
"id": "servUsApi.admin.creditKickbackKash",
"parameterOrder": [
"userId",
"creditAmount"
],
"parameters": {
"userId": {
"format": "int64",
"location": "path",
"required": true,
"type": "string"
},
"creditAmount": {
"location": "path",
"required": true,
"type": "number"
}
},
"path": "creditKickbackKash/{userId}/{creditAmount}",
"response": {
"$ref": "ResultDTO"
},
"scopes": [
"https://www.googleapis.com/auth/userinfo.email"
]
}
Is anyone else having this issue? How can I get the discovery document generation to properly format the document including double number types?
I had the same problem. I rolled back from 1.9.50 to 1.9.48 and the problem is gone.
I have an existing rails3 application with SendGrid Service integration based on SMTP relay, and subscribed to Event Notification Webhooks.
I've got reminder email from Service, informing about impending change to SendGrid's service, and I need make some changes to match new version of Event Notification Webhooks v3.
Email I got contains instructions about How To Upgrade:
Review the documentation to understand how to consume this new version's events.
Implement changes on your side to handle the new in-formatting of event data.
Make changes on SendGrid's configuration page
I wounder, what changes now need I implement on my site? I read manual for v3, but there no information about specifications differences between old and new versions.
Previously, the SendGrid event webhook sent improper batched JSON, with documents seperated by line breaks:
{ "email": "john.doe#sendgrid.com", "timestamp": 1337197600, "smtp-id": "<4FB4041F.6080505#sendgrid.com>", "event": "processed" }
{ "email": "john.doe#sendgrid.com", "timestamp": 1337966815, "category": "newuser", "event": "click", "url": "http://sendgrid.com" }
{ "email": "john.doe#sendgrid.com", "timestamp": 1337969592, "smtp-id": "<20120525181309.C1A9B40405B3#Example-Mac.local>", "event": "processed" }
Today, with v3 it sends proper JSON as such:
[
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337197600,
"smtp-id": "<4FB4041F.6080505#sendgrid.com>",
"event": "processed"
},
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337966815,
"category": "newuser",
"event": "click",
"url": "http://sendgrid.com"
},
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337969592,
"smtp-id": "<20120525181309.C1A9B40405B3#Example-Mac.local>",
"event": "processed"
}
]
If you'd previously been dealing with non-batched events you'll need to adjust your code so that it interprets an array, rather than just a single document, and then loops through said array. Put into code:
# This
consume_data(params)
# Becomes this
params.each { |doc|
consume_data(doc)
}