0
votes

I want to create/subscribe a new (simulated) device with my local machine in azure IoT Hub.

I am using python 3.6.4 (64bit) on windows7 (64bit) machine and run the code with spyder.

Installed, relevant packages:

  • azure-iothub-device-client (1.3.1)
  • azure-iothub-service-client (1.3.1)
  • spyder (3.2.8)

I followed the steps from here: CreateDeviceIdentity.py

The code snipped:

import sys
import iothub_service_client

CONNECTION_STRING = "myConnectionString"
DEVICE_ID = "pythonDevice_1"

def print_device_info(title, iothub_device):
    print ( title + ":" )
    print ( "iothubDevice.deviceId = {0}".format(iothub_device.deviceId) )
    print ( "iothubDevice.primaryKey = {0}".format(iothub_device.primaryKey) )
    print ( "iothubDevice.secondaryKey = {0}".format(iothub_device.secondaryKey) )
    print ( "iothubDevice.connectionState = {0}".format(iothub_device.connectionState) )
    print ( "iothubDevice.status = {0}".format(iothub_device.status) )
    print ( "iothubDevice.lastActivityTime = {0}".format(iothub_device.lastActivityTime) )
    print ( "iothubDevice.cloudToDeviceMessageCount = {0}".format(iothub_device.cloudToDeviceMessageCount) )
    print ( "iothubDevice.isManaged = {0}".format(iothub_device.isManaged) )
    print ( "iothubDevice.authMethod = {0}".format(iothub_device.authMethod) )
    print ( "" )

#def iothub_createdevice():
try:
    iothub_registry_manager = iothub_service_client.IoTHubRegistryManager(CONNECTION_STRING)
    primary_key = ""
    secondary_key = ""
    auth_method = iothub_service_client.IoTHubRegistryManagerAuthMethod.SHARED_PRIVATE_KEY
    new_device = iothub_registry_manager.create_device(DEVICE_ID, primary_key, secondary_key, auth_method)
    print_device_info("CreateDevice", new_device)

except iothub_service_client.IoTHubError as iothub_error:
    print ( "Unexpected error {0}".format(iothub_error) )
    #return
except KeyboardInterrupt:
    print ( "iothub_createdevice stopped" )


'''
if __name__ == '__main__':
    print ( "" )
    print ( "Python {0}".format(sys.version) )
    print ( "Creating device using the Azure IoT Hub Service SDK for Python" )
    print ( "" )
    print ( "    Connection string = {0}".format(CONNECTION_STRING) )
    print ( "    Device ID         = {0}".format(DEVICE_ID) )

    iothub_createdevice()
'''

If I run this code I always get the error:

Unexpected error IoTHubRegistryManager.create_device, IoTHubRegistryManagerResult.HTTPAPI_ERROR

I found the (or a similar) error on several pages in the inet but never got a working solution for it. The other code example from the microsoft documentation 1 (SimulatedDevice.py) works fine.

addon: the error can also be reproduced when running the script by command line. The complete error log:

Error: Time:Thu Apr 5 08:59:55 2018 File:C:\release\iot-sdks-internals\release\python\automation\az iotsdk_pytools\src\c\c-utility\adapters\httpapi_winhttp.c Func:HTTPAPI_Init Line:142 WinHttpOpen failed.

Error: Time:Thu Apr 5 08:59:55 2018 File:C:\release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\c-utility\adapters\httpapi_winhttp.c Func:HTTPAPI_Init Line:142 GetLastError: Falscher Parameter.

Error: Time:Thu Apr 5 08:59:55 2018 File:C:\release\iot-sdks-internals\release\python\automation\aziotsdk_pytools\src\c\c-utility\src\httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:475 unable to recover sending to a working state

Error: Time:Thu Apr 5 08:59:55 2018 File:C:\release\iot-sdks-internals\release\python\automation\az iotsdk_pytools\src\c\iothub_service_client\src\iothub_registrymanager.c Func:sendHttpRequestCRUD Line:982 HTTPAPIEX_SAS_ExecuteRequest failed Unexpected error IoTHubRegistryManager.create_device, IoTHubRegistryManagerResult.HTTPAPI_ERROR

3
Can you reproduce this issue run the Python script using command line? Also please share the detailed error code with us if it exits, like this out of memory issue?Fei Xue - MSFT
hi, no its no memeory error. Please see my additional entry in the first question tag.eid
Based on the error message, the issue is occurred in HTTPAPI_Init function. Did you build the python SDK for Azure Iot yourself or just download it via pip? What's that line of code? To narrow down this issue, I also suggest that you try to create a device identity using other language SDK( eg. .Net) to see whether the issue is relative to environment or specific SDK.Fei Xue - MSFT
I downloaded and installed the two azure-iot packages via pip. But I also doanloaded the SDK from git but was not able to build it by ...\azure-iot-sdk-python\build_all\windows\build_client.cmd. On a raspberry pi I was able to build it an created a iothub_client.so. But same error as above (HTTPAPI_ERROR) when running the iothub_registrymanager_sample.py or CreateDeviceIdentity.py. The other sampleCode (iothub_client_sample.py or SimulatedDevice.py) still works fine on both systems. Running the sample code for c-sharp works.eid
This issue already fixed in the latest version SDK(1.3.3). Please let me know whether it works for you.Fei Xue - MSFT

3 Answers

2
votes

This is old by now, but I keep running into similar stuff and wanted to share some solutions I've found.

I had this same problem with the newest pip installs (1.4.5) and python3.7 and diagnosed it to incorrect openssl / curl libraries. I resolved it by compiling the Azure IOTHub Python SDK myself, which creates .so files for the device and service clients that you can just drop in your code directory next to your python files.

Here's how I tracked it down:

  1. Use pip to find the directory for the module:

    pip3 show azure-iothub-service-client
    
  2. This pointed me to /usr/local/lib/python3.7/site-packages. Underneath that was the folder the import uses - /iothub_service_client. I used Apple's 'otool' utility to list the libraries that the service client calls (this can be done on linux using 'ldd'):

    otool -L /usr/local/lib/python3.7/site-packages/iothub_service_client/iothub_service_client.so
    
  3. That showed me that the library was using the libcurl that comes with MacOSX:

    /usr/local/lib/python3.7/site-packages/iothub_service_client/iothub_service_client.so:
        @rpath/iothub_service_client.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/local/opt/boost-python3/lib/libboost_python37-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/Python (compatibility version 3.7.0, current version 3.7.0)
        /usr/lib/libcurl.4.dylib (compatibility version 7.0.0, current version 9.0.0)
        /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1452.23.0)
        /System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork (compatibility version 1.0.0, current version 897.15.0)
        /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)
        /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1452.23.0)
    

I remembered something about the new MacOS LibreSSL-based curl not working for the MSFT clients, and even though I had my brew-installed curl library directory set in a DYLD_LIBRARY_PATH env variable, I decided to compile the iothub service & device clients myself to see if it fixed the problem. I largely followed the suggestions at https://github.com/Azure/azure-iot-sdk-python/blob/master/doc/python-devbox-setup.md.

Some additional things I did to ensure a successful compile:

  1. First, get brew info for curl & openssl using brew info <package>
  2. The brew versions of curl and openssl were already in my path. They shouldn't be required for a compile, but I've had other setup scripts fail because of version checks against curl and openssl, so they may be needed for the staging scripts. brew info gives you the commands you need to put them into your path. It'll be something like:

    echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.bash_profile
    echo 'export PATH="/usr/local/opt/curl/bin:$PATH"' >> ~/.bash_profile
    
  3. Make sure the build will use your libs and includes for curl and openssl:

    export LDFLAGS="-L/usr/local/opt/curl/lib -L/usr/local/opt/openssl/lib"
    export CPPFLAGS="-I/usr/local/opt/curl/include -I/usr/local/opt/openssl/include"
    
  4. Since these SDKs use Boost, you need to get that installed properly. I finally found the right command to install boost and boost-python for python3 without it installing python2 and dragging in a ton of extra stuff:

    brew install boost-python3 --with-python3 --without-python
    

Once all that is good, you should be able to compile the clients with no problems. The latest version of the SDK has support for Python 3.7, and for the first time in a year, I had an error-free compile on first go. :D

1
votes

Initially, I also got the same error that you got. The solution is uninstall both of the pip packages and install the updated version. If you run the sample code, it is supposed to work fine.

0
votes

I was able to run this code without a problem. Can you confirm if your IoT Hub is working properly? Did you copy the IoT Hub connection string instead of a device connection string?

enter image description here