'Called on the client side to initiade a control request.
Composes a message with the request and sends it to the device(s).
Does not block, the callback will be called when the device(s)
has responded.
Arguments:
from_jid        -- The jid of the requester
to_jid          -- The jid of the device(s)
callback        -- The callback function to call when data is availble.
The callback function must support the following arguments:
from_jid    -- The jid of the responding device(s)
result      -- The result of the control request. Valid values are:
"OK"             - Control request completed successfully
"NotFound"       - One or more nodes or fields are missing
"InsufficientPrivileges" - Not authorized.
"Locked"         - Field(s) is locked and cannot
be changed at the moment.
"NotImplemented" - Request feature not implemented.
"FormError"      - Error while setting with
a form (not implemented).
"OtherError"     - Indicates other types of
errors, such as timeout.
Details in the error_msg.
nodeId      -- [optional] Only applicable when result == "error"
List of node Ids of failing device(s).
fields      -- [optional] Only applicable when result == "error"
List of fields that failed.[optional] Mandatory when result == "rejected" or "failure".
error_msg   -- Details about why the request failed.
fields          -- Fields to set. List of tuple format: (name, typename, value).
nodeIds         -- [optional] Limits the request to the node Ids in this list.'

def set_request(self, from_jid, to_jid, callback, fields, nodeIds=None):

    iq = self.xmpp.Iq()
    iq['from'] = from_jid
    iq['to'] = to_jid
    seqnr = self._get_new_seqnr()
    iq['id'] = seqnr
    iq['type'] = 'set'
    if (nodeIds is not None):
        for nodeId in nodeIds:
            iq['set'].add_node(nodeId)
    if (fields is not None):
        for (name, typename, value) in fields:
            iq['set'].add_data(name=name, typename=typename, value=value)
    self.sessions[seqnr] = {'from': iq['from'], 'to': iq['to'], 'callback': callback}
    iq.send(block=False)
