amenzhinsky / iothub

Azure IoT Hub SDK for Golang
MIT License
53 stars 57 forks source link

Send a message from a device to the hub #29

Open SimonSimCity opened 3 years ago

SimonSimCity commented 3 years ago

I was trying to send a message from a device running a module (my go application) to the IoT hub.

On the device I have iotedge installed in version 1.0.10.1. At first I tried to build the sample, provided in the readme:

package main

import (
    "context"
    "log"
    "os"

    "github.com/amenzhinsky/iothub/iotdevice"
    iotmqtt "github.com/amenzhinsky/iothub/iotdevice/transport/mqtt"
)

func main() {
    c, err := iotdevice.NewFromConnectionString(
        iotmqtt.New(), os.Getenv("IOTHUB_DEVICE_CONNECTION_STRING"),
    )
    if err != nil {
        log.Fatal(err)
    }

    // connect to the iothub
    if err = c.Connect(context.Background()); err != nil {
        log.Fatal(err)
    }

    // send a device-to-cloud message
    if err = c.SendEvent(context.Background(), []byte(`hello`)); err != nil {
        log.Fatal(err)
    }
}

Even though this works, it requires me to add the connection string to the environment variables of my container. On a container for a module I have the following environment variables set:

After looking a bit around in the code, I found the function NewModuleFromEnvironment() which is reading most of those variables, so I adjusted the code and tried to run it:

package main

import (
    "context"
    "log"

    "github.com/amenzhinsky/iothub/iotdevice"
    iotmqtt "github.com/amenzhinsky/iothub/iotdevice/transport/mqtt"
)

func main() {
    c, err := iotdevice.NewModuleFromEnvironment(
        iotmqtt.New(),
        false,
    )
    if err != nil {
        log.Fatal(err)
    }

    // connect to the iothub
    if err = c.Connect(context.Background()); err != nil {
        log.Fatal(err)
    }

    // send a device-to-cloud message
    if err = c.SendEvent(context.Background(), []byte(`hello`)); err != nil {
        log.Fatal(err)
    }
}

My application always exits with:

2020/11/12 15:15:02 Connect:
2020/11/12 15:15:02 not Authorized

And I'm unable to tell what part is missing. Other packages can send messages quite fine when only the selected settings are provided. Any idea how I can send a message from a Go module without providing the connection string to each and every module?

siredmar commented 3 years ago

Same issue here. Did you find a solution yet?

amenzhinsky commented 3 years ago

All module required variables are listed here: https://github.com/amenzhinsky/iothub/blob/master/common/sas.go#L59

Can you make sure you have everything you need?

Not sure, probably something could change over a version.

siredmar commented 3 years ago

@amenzhinsky thanks for responding. I guess the problem is that the current implementation needs the device connection string to extract things like SharedAccessKey. If i look at the python SDK for Azure IoT Hub (https://github.com/Azure/azure-iot-sdk-python/blob/e7e8bbeed79063873ef9df3bf2040b2f92fb01a7/azure-iot-device/azure/iot/device/iothub/abstract_clients.py#L559) i see that there are two ways:

  1. (default) use with iot hsm object (https://github.com/Azure/azure-iot-sdk-python/blob/e7e8bbeed79063873ef9df3bf2040b2f92fb01a7/azure-iot-device/azure/iot/device/iothub/abstract_clients.py#L613) This way it seems to connect to talk to some Azure edge module (hub or agent) to make the credential exchange (https://github.com/Azure/azure-iot-sdk-python/blob/e7e8bbeed79063873ef9df3bf2040b2f92fb01a7/azure-iot-device/azure/iot/device/iothub/edge_hsm.py#L25)
  2. Use with device connection string (https://github.com/Azure/azure-iot-sdk-python/blob/e7e8bbeed79063873ef9df3bf2040b2f92fb01a7/azure-iot-device/azure/iot/device/iothub/abstract_clients.py#L572)

How things look, this library implements only way the second way (device connection string). This however is a problem, because i cannot put the device connection string in a generic deployment matching several devices. Do you have any suggestions?

siredmar commented 3 years ago

Hi! I fixed my problem. I did use the iotmqtt.New() which didn't return a module mqtt client.

I use this now without providing the connection string. Works like a charm.

c, _ := iotdevice.NewModuleFromEnvironment(iotmqtt.NewModuleTransport(), true)
amenzhinsky commented 3 years ago

You're right transports API is a bit confusing, I think we need separate module and device transport interfaces or join them together.

Cavalletta98 commented 11 months ago

i'm trying as suggested by @siredmar but still gettin not autorized

matthewfarstad commented 8 months ago

I'm trying to send a message but when it arrives its all jumbled. The internet says that I need to set these values in systemProperties

"iothub-content-type": "application/json",
"iothub-content-encoding": "utf-8",

Is this possible?

matthewfarstad commented 8 months ago

Also how to set "dt-subject": "<string goes here>"

matthewfarstad commented 8 months ago

Seems like common.Message needs to be modified.