通过 IoTHub/Xamarin App/ESP8266 的双向通信
Bi-Directional Communication via IoTHub/Xamarin App/ESP8266
正在开发一款新产品,该产品将使用 ESP8266、Xamarin 应用程序和 Azure IoTHub 为客户的设备启用双向通信。
我们的 C2D(云 2 设备)和 D2C(设备 2 云)通信在应用程序和 ESP 上都正常工作,但我们没有找到任何关于设置 IoTHub 来解释传入的遥测消息的信息,处理它们各自的 "To:" 字段并将它们放回 C2D 主题,这应该允许我们的目标设备接收它。
我们尝试过的:
- 逻辑应用程序。能够触发队列中的传入消息,但不确定要执行什么 HTTP 请求才能将其转发回 C2D 事件中心。
- 我们已经成功地将每条消息转发到队列中,但是 Xamarin 的 PCL 库无法连接到 Azure 服务总线队列(真可惜)。
我找到了一个微软实习生的参考,为车库门开启器开发直接设备到设备通信,但她使用的库仅适用于 UWP 应用程序,这并不是那么方便,当我们真的想要瞄准 iOS、Android 和 UWP(首先选择 Xamarin 的原因)。
有没有人能够使用 Azure 门户触发 C2D 条件事件?
通过与 Microsoft Azure 团队的一些对话,我们确定将网络作业与队列路由相结合是最适合我们的解决方案。
所有消息都路由到队列,当它们到达队列时,webjob 处理消息并使用 ServiceBus 消息传递对象发送消息以将云发送到设备响应消息。
这是供任何想使用它的人使用的代码。
只要消息的原始发件人在代理消息中指定 "To" 属性,它就会被传送到注册表中的那个设备。您将需要服务总线和 Azure.Messaging NuGet 包才能使用它。此代码将复制整个消息并将整个内容发送到所需的注册设备。
private const string queueName = "<queue_name>";
private const string IoTHubConnectionString = "HostName=<your_host>;SharedAccessKeyName=<your_service_user>;SharedAccessKey=<your sas>";
// This function will get triggered/executed when a new message is written
// on an Azure Queue called <queue_name>.
public static void ReceiveQueueMessages(
[ServiceBusTrigger(queueName)] BrokeredMessage message,
TextWriter log)
{
if (message.To == null)
{
//message = null
return;
}
else
{
//Retrieve the message body regardless of the content as a stream
Stream stream = message.GetBody<Stream>();
StreamReader reader;
if (stream != null)
reader = new StreamReader(stream);
else
reader = null;
string s;
Message serviceMessage;
if ( reader != null )
{
s = reader.ReadToEnd();
serviceMessage = new Microsoft.Azure.Devices.Message(Encoding.ASCII.GetBytes(s));
}
else
{
serviceMessage = new Microsoft.Azure.Devices.Message();
}
foreach (KeyValuePair<string, object> property in message.Properties)
{
serviceMessage.Properties.Add(property.Key, property.Value.ToString());
}
SendToIoTHub(message.To.ToString(), serviceMessage);
}
}
static async void SendToIoTHub(string target, Microsoft.Azure.Devices.Message message)
{
// Write it back out to the target device
ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(IoTHubConnectionString);
var serviceMessage = message;
serviceMessage.Ack = DeliveryAcknowledgement.Full;
serviceMessage.MessageId = Guid.NewGuid().ToString();
try
{
await serviceClient.SendAsync(target, serviceMessage);
}
catch
{
await serviceClient.CloseAsync();
return;
}
await serviceClient.CloseAsync();
}
正在开发一款新产品,该产品将使用 ESP8266、Xamarin 应用程序和 Azure IoTHub 为客户的设备启用双向通信。
我们的 C2D(云 2 设备)和 D2C(设备 2 云)通信在应用程序和 ESP 上都正常工作,但我们没有找到任何关于设置 IoTHub 来解释传入的遥测消息的信息,处理它们各自的 "To:" 字段并将它们放回 C2D 主题,这应该允许我们的目标设备接收它。
我们尝试过的:
- 逻辑应用程序。能够触发队列中的传入消息,但不确定要执行什么 HTTP 请求才能将其转发回 C2D 事件中心。
- 我们已经成功地将每条消息转发到队列中,但是 Xamarin 的 PCL 库无法连接到 Azure 服务总线队列(真可惜)。
我找到了一个微软实习生的参考,为车库门开启器开发直接设备到设备通信,但她使用的库仅适用于 UWP 应用程序,这并不是那么方便,当我们真的想要瞄准 iOS、Android 和 UWP(首先选择 Xamarin 的原因)。
有没有人能够使用 Azure 门户触发 C2D 条件事件?
通过与 Microsoft Azure 团队的一些对话,我们确定将网络作业与队列路由相结合是最适合我们的解决方案。
所有消息都路由到队列,当它们到达队列时,webjob 处理消息并使用 ServiceBus 消息传递对象发送消息以将云发送到设备响应消息。
这是供任何想使用它的人使用的代码。
只要消息的原始发件人在代理消息中指定 "To" 属性,它就会被传送到注册表中的那个设备。您将需要服务总线和 Azure.Messaging NuGet 包才能使用它。此代码将复制整个消息并将整个内容发送到所需的注册设备。
private const string queueName = "<queue_name>";
private const string IoTHubConnectionString = "HostName=<your_host>;SharedAccessKeyName=<your_service_user>;SharedAccessKey=<your sas>";
// This function will get triggered/executed when a new message is written
// on an Azure Queue called <queue_name>.
public static void ReceiveQueueMessages(
[ServiceBusTrigger(queueName)] BrokeredMessage message,
TextWriter log)
{
if (message.To == null)
{
//message = null
return;
}
else
{
//Retrieve the message body regardless of the content as a stream
Stream stream = message.GetBody<Stream>();
StreamReader reader;
if (stream != null)
reader = new StreamReader(stream);
else
reader = null;
string s;
Message serviceMessage;
if ( reader != null )
{
s = reader.ReadToEnd();
serviceMessage = new Microsoft.Azure.Devices.Message(Encoding.ASCII.GetBytes(s));
}
else
{
serviceMessage = new Microsoft.Azure.Devices.Message();
}
foreach (KeyValuePair<string, object> property in message.Properties)
{
serviceMessage.Properties.Add(property.Key, property.Value.ToString());
}
SendToIoTHub(message.To.ToString(), serviceMessage);
}
}
static async void SendToIoTHub(string target, Microsoft.Azure.Devices.Message message)
{
// Write it back out to the target device
ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(IoTHubConnectionString);
var serviceMessage = message;
serviceMessage.Ack = DeliveryAcknowledgement.Full;
serviceMessage.MessageId = Guid.NewGuid().ToString();
try
{
await serviceClient.SendAsync(target, serviceMessage);
}
catch
{
await serviceClient.CloseAsync();
return;
}
await serviceClient.CloseAsync();
}