2

I am trying to call a method associated with the device using connection string. I tried with the samples provided with other languages I am able to call the method in the device. eg: "setState" or "getState" of the lamp. But I am not able to implement in iOS using swift.

I tried to match parameter parameter requirement by referring to the C sample. But I am getting 1. Func:sendHttpRequestDeviceMethod Line:337 Http Failure status code 400. 2. Func:IoTHubDeviceMethod_Invoke Line:492 Failure sending HTTP request for device method invoke

     var status :Int32! = 0
     var deviceId = "simulated_device_one";
     var  methodName = "GetState";
    var uint8Pointer:UnsafeMutablePointer<UInt8>!
    uint8Pointer = UnsafeMutablePointer<UInt8>.allocate(capacity:8)

    var size = size_t(10000)
    var bytes: [UInt8] = [39, 77, 111, 111, 102, 33, 39, 0]
    uint8Pointer?.initialize(from: &bytes, count: 8)
    var intValue : UnsafeMutablePointer<UInt8>?
    intValue = UnsafeMutablePointer(uint8Pointer)
    var char: UInt8 =  UInt8(20)
    var charPointer = UnsafeMutablePointer<UInt8>(&char)
    var prediction = intValue
    let serviceClientDeviceMethodHandle =  IoTHubDeviceMethod_Create(service_client_handle)

    let payLoad = "test"

    var responsePayload = ""


    let invoke = IoTHubDeviceMethod_Invoke(serviceClientDeviceMethodHandle, deviceId, methodName, payLoad , 100, &status, &prediction,&size )

I want to call a method in the device using IoTHubDeviceMethod_Invoke

joy son
  • 555
  • 6
  • 15
  • The payload must be valid JSON: https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-direct-methods – silent Aug 21 '19 at 14:03
  • Calling this method requires no payload. I made sure it is working without payload with the sample code provided for node js. – joy son Aug 21 '19 at 15:49
  • well then trying to remove the payload in your example as well, instead of using "test" – silent Aug 21 '19 at 15:51
  • We cant send null value beacase of this check function if ((serviceClientDeviceMethodHandle == NULL) || (deviceId == NULL) || (methodName == NULL) || (methodPayload == NULL) || (responseStatus == NULL) || (responsePayload == NULL) || (responsePayloadSize == NULL)) { LogError("Input parameter cannot be NULL"); result = IOTHUB_DEVICE_METHOD_INVALID_ARG; } " I tried with sending with an empty string "" but no progress it is resulting in the same error. – joy son Aug 22 '19 at 17:51
  • Then try sending an empty Json `”{}”` – silent Aug 22 '19 at 18:39
  • 1
    Hey. Yes it is working with with "{}" and some other modifications. I will ping the answer. – joy son Aug 26 '19 at 06:23
  • Pease post working code snippet. – Ankit Sharma Sep 06 '19 at 13:03
  • @AnkitSharma This is my first answer so if there is any wrong formatiing sorry any clarification needed ask it in the comment. – joy son Sep 10 '19 at 07:08

2 Answers2

3

You can download View controller file which I worked on from here

1.Create Connection in view did load

// declaring your connection string you can find it in azure iot dashboard
private let connectionString = "Enter your connection String";


// creating service handler 
private var service_client_handle: IOTHUB_SERVICE_CLIENT_AUTH_HANDLE!;


// handler for the method invoke   
private var iot_device_method_handle:IOTHUB_SERVICE_CLIENT_DEVICE_METHOD_HANDLE!;



// In view did load establish the connection
service_client_handle = IoTHubServiceClientAuth_CreateFromConnectionString(connectionString)

if (service_client_handle == nil) {
    showError(message: "Failed to create IoT Service handle", sendState: false)
}
  1. create method invoke function

I created it based on the demo provided for sending message

func openIothubMethodInvoke() -> Bool
{
    print("In openIotHub method invoke")
    let result: Bool;
    iot_device_method_handle = IoTHubDeviceMethod_Create(service_client_handle);
    let testValue : Any? = iot_device_method_handle;
    if (testValue == nil) {
        showError(message: "Failed to create IoT devicemethod", sendState: false);
        result = false;
    }
    else
    {
        result = true;
    }
    return result;
}
  1. call method invoke

** this is the main function for calling the method

func methodInvoke()
    {
        let testValue : Any? = iot_device_method_handle;
        if (testValue == nil && !openIothubMethodInvoke() ) {
            print("Failued to open IoThub messaging");
        }
        else {
            let size = UnsafeMutablePointer<Int>.allocate(capacity: 1)
            let responseStatus = UnsafeMutablePointer<Int32>.allocate(capacity: 1)
      // Payload is the main change it is like specifying the format
            var payload = UnsafeMutablePointer<UnsafeMutablePointer<UInt8>?>.allocate(capacity: 1)
            // if  payload is not expected please send empty json "{}"
            let result = IoTHubDeviceMethod_Invoke(iot_device_method_handle, "nameOfTheDeviceYouWantToCallOn", "MethodName", "{payload you want to send}", 100, responseStatus, payload , size)
      //  extracting the data from response
            let b = UnsafeMutableBufferPointer(start: payload.pointee, count:  size.pointee)

            let data = Data(buffer: b)

           let str = String(bytes: data, encoding: .utf8)
            print(str)
            do{
                let value = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
                  print(value)
            }catch{
                print(error)
            }
        }
    }
Adithya
  • 1,688
  • 1
  • 10
  • 18
joy son
  • 555
  • 6
  • 15
2

As discussed above: the payload needs to be valid JSON. Even an empty json will do such as {}

silent
  • 14,494
  • 4
  • 46
  • 86