通过 IoTHub/Xamarin App/ESP8266 的双向通信

Bi-Directional Communication via IoTHub/Xamarin App/ESP8266

正在开发一款新产品,该产品将使用 ESP8266、Xamarin 应用程序和 Azure IoTHub 为客户的设备启用双向通信。

我们的 C2D(云 2 设备)和 D2C(设备 2 云)通信在应用程序和 ESP 上都正常工作,但我们没有找到任何关于设置 IoTHub 来解释传入的遥测消息的信息,处理它们各自的 "To:" 字段并将它们放回 C2D 主题,这应该允许我们的目标设备接收它。

我们尝试过的:

  1. 逻辑应用程序。能够触发队列中的传入消息,但不确定要执行什么 HTTP 请求才能将其转发回 C2D 事件中心。
  2. 我们已经成功地将每条消息转发到队列中,但是 Xamarin 的 PCL 库无法连接到 Azure 服务总线队列(真可惜)。

我找到了一个微软实习生的参考,为车库门开启器开发直接设备到设备通信,但她使用的库仅适用于 UWP 应用程序,这并不是那么方便,当我们真的想要瞄准 iOS、Android 和 UWP(首先选择 Xamarin 的原因)。

https://blogs.windows.com/buildingapps/2016/09/08/device-to-device-communication-with-azure-iot-hub/#ykPJrVE734GpSEzV.97

有没有人能够使用 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();
    }