Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send a message from a device to the hub #29

Open
SimonSimCity opened this issue Nov 12, 2020 · 9 comments
Open

Send a message from a device to the hub #29

SimonSimCity opened this issue Nov 12, 2020 · 9 comments

Comments

@SimonSimCity
Copy link

SimonSimCity commented Nov 12, 2020

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:

  • IOTEDGE_APIVERSION
  • IOTEDGE_AUTHSCHEME
  • IOTEDGE_DEVICEID
  • IOTEDGE_GATEWAYHOSTNAME
  • IOTEDGE_IOTHUBHOSTNAME
  • IOTEDGE_MODULEGENERATIONID
  • IOTEDGE_MODULEID
  • IOTEDGE_WORKLOADURI
  • RuntimeLogLevel
  • PATH

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
Copy link

Same issue here. Did you find a solution yet?

@amenzhinsky
Copy link
Owner

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
Copy link

@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
Copy link

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
Copy link
Owner

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

@Cavalletta98
Copy link

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

@matthewfarstad
Copy link

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
Copy link

matthewfarstad commented Feb 6, 2024

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

@matthewfarstad
Copy link

Seems like common.Message needs to be modified.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants