none
[Python][Azure IoT Hub] IoT Hub - Complete and Reject a cloud-to-device message getting error 412 RRS feed

  • Question

  • Hi,

    I am writing Python application using Azure IoT Hub REST API. It looks like documentation is not correct and IoT SDK too.

    1. https://msdn.microsoft.com/en-us/library/mt605155.aspx

    If I follow this document I get HTTP Error 405: Method Not Allowed

    2. azure-iot-sdks

    I tried to copy behavior of IoT SDKs. But there is problem too. If I try to call Complete for Azure IoT Cloud to Device mesaage I get HTTP Error 412: Precondition Failed Same for Reject

    I use ETag for If-Match HTTP header and MessageId in URL.

    headers = {

       

    'Authorization': sas,

       

    'If-Match': etag

        }

    req =

    urllib.request.Request('https://'+ HOST + url + "/messages/devicebound/"+ messageid + "?api-version=2015-08-15-preview",                            

                                 headers = headers,

                                 method =

    'DELETE')

    What is correct call for Complete and Reject?



    Thursday, December 31, 2015 12:07 PM

All replies

  • Hello,

     

    We are researching on the query and would get back to you soon on this. I apologize for the inconvenience and appreciate your time and patience in this matter.

     

    Best Regards,

    Kamalakar K

    Thursday, December 31, 2015 7:05 PM
  • Any progress?
    Wednesday, January 6, 2016 7:51 PM
  • No progress? I expected priority MSDN Support. Very disappointed.
    Saturday, January 16, 2016 1:07 PM
  • Hi,
    Thank you for your patience and apologize for delay.  I had reported this issue and we will get back to you later as soon as we can.
    Appreciate your understanding.
    Best Regards,

    Will


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Sunday, January 17, 2016 2:42 PM
    Moderator
  • Hi,

    I found answer. There is issue in documentation and maybe behavior.

    1. If-Match header doesn't have any impact

    2. Correct url is

    https://{IoTHubName}.azure-devices.net/devices/{deviceId}/messages/devicebound/{E-tag}?api-version={api-version}

    3. In message header is E-Tag in quotes. You must delete quotes before you use it in url

    ETag: "41636a1d-8fb5-4cdc-abca-155b9db9e356"

    Final url can looks like this

    https://stepanb.azure-devices.net/devices/stepanb-rpi-02/messages/deviceBound/89429ac5-8578-4e62-824b-a9dddd38ff11?api-version=2015-08-15-preview

    Here is full example in Python:

    import hmac
    import base64
    import urllib.parse
    import urllib.request
    import time
    
    # START: Azure Evet Hub settings
    KEY = "xxxx";
    HOST = "xxxx.azure-devices.net";
    DEVICE_NAME = "xxxx";
    # END: Azure Evet Hub settings
    
    # current time +10 minutes
    timestamp = int(time.time()) + (10 * 60)
    url = "/devices/" + DEVICE_NAME;
    urlToSign = urllib.parse.quote(HOST + url, safe='') 
    
    h = hmac.new(base64.b64decode(KEY), 
                 msg = "{0}\n{1}".format(urlToSign, timestamp).encode('utf-8'),
                 digestmod = 'sha256')
    
    sas = "SharedAccessSignature sr={0}&sig={1}&se={2}".format(urlToSign, 
                                                               urllib.parse.quote(base64.b64encode(h.digest()), safe = ''),
                                                               timestamp)
    
    print(sas)
    headers = {
        'Authorization': sas,
        'Content-Type' : 'application/json'
        }
    
    data = b"{message: 'Hello from Python'}"
    req = urllib.request.Request('https://' + HOST + url + "/messages/events?api-version=2015-08-15-preview",
                                 data,
                                 headers,
                                 method = 'POST')
    
    with urllib.request.urlopen(req) as f:
        print(f.code)
    
    headers = {
        'Authorization': sas
        }
    
    req = urllib.request.Request('https://' + HOST + url + "/messages/devicebound?api-version=2015-08-15-preview",                             
                                 headers = headers,
                                 method = 'GET')
    
    print('---------------------------------')
    with urllib.request.urlopen(req) as f:
        # Process headers
        print(f.info())
        etag = f.info()['ETag'].strip('"')
        print(etag)
        # message
        print(f.read().decode('utf-8'))
    
    
    if messageid == None:
        exit()
    
    headers = {
        'Authorization': sas,
        'If-Match' : etag
        }
    
    url = 'https://' + HOST + url + "/messages/deviceBound/" + etag + "?api-version=2015-08-15-preview"
    req = urllib.request.Request(url,                             
                                 headers = headers,
                                 method = 'DELETE')
    
    print('---------------------------------')
    with urllib.request.urlopen(req) as f:
        print(f.code)

    Stepan


    Sunday, January 17, 2016 3:14 PM
  • Hello Stepan

    At your code: which SAS token should be used?

    The SAS Token generated for the IOT Hub in general? or the SAS Token generated for the specific device?

    After running your code I receive this error:

    urllib.error.HTTPError: HTTP Error 401: Unauthorized

    Any idea's?

    Kind Regards

    Nathan Hofstee

    Friday, February 19, 2016 2:24 PM
  • SAS uses device specific security key.
    Friday, February 19, 2016 2:46 PM
  • Thank you. I can now send messages to IOT Hub from Python with HTTP.
    Monday, February 22, 2016 8:38 AM
  • Do you have a Python script which uses HTTP to read the message's send?
    Monday, February 22, 2016 9:30 AM