iothub icon indicating copy to clipboard operation
iothub copied to clipboard

Send a message from a device to the hub

Open SimonSimCity opened this issue 4 years ago • 9 comments

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?

SimonSimCity avatar Nov 12 '20 15:11 SimonSimCity

Same issue here. Did you find a solution yet?

siredmar avatar Feb 24 '21 11:02 siredmar

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.

amenzhinsky avatar Feb 24 '21 11:02 amenzhinsky

@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 avatar Feb 24 '21 12:02 siredmar

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)

siredmar avatar Feb 25 '21 09:02 siredmar

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

amenzhinsky avatar Feb 25 '21 12:02 amenzhinsky

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

Cavalletta98 avatar Oct 19 '23 07:10 Cavalletta98

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 avatar Feb 06 '24 18:02 matthewfarstad

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

matthewfarstad avatar Feb 06 '24 18:02 matthewfarstad

Seems like common.Message needs to be modified.

matthewfarstad avatar Feb 06 '24 19:02 matthewfarstad