1

I had divided my software update process in various stages like (download, unzip, pre-install, install, post-install). I am setting reported properties at every stage accordingly. But these properties are not updating during installation process (i.e. unable to see changes in reported property in device twin on azure portal) but at the end of installation I am getting callback responses for all the set "reported" properties.

I am working on software update with Azure IOT using python device sdk. For this I have modified the sample given in SDK (i.e. iothub_client_sample_class.py file). I am using device twin for updating the software. I had created "desired" property for "software_version" in device twin. Once "desired" property for "software_version" is changed, software update process is started. Software update process perform various operation so I have divided this process in various stages. I am sending "reported" properties for ever stage to IotHub. But these "reported" are not updating in seqence in device twin reported property on azure portal.

import random
import time
import sys
import iothub_client
import json
from iothub_client import IoTHubClient, IoTHubClientError,  IoTHubTransportProvider
from iothub_client import IoTHubMessage, IoTHubMessageDispositionResult, IoTHubError, DeviceMethodReturnValue
from iothub_client_args import get_iothub_opt, OptionError

# HTTP options
# Because it can poll "after 9 seconds" polls will happen effectively
# at ~10 seconds.
# Note that for scalabilty, the default value of minimumPollingTime
# is 25 minutes. For more information, see:
# https://azure.microsoft.com/documentation/articles/iot-hub-devguide/#messaging
TIMEOUT = 241000
MINIMUM_POLLING_TIME = 9

# messageTimeout - the maximum time in milliseconds until a message times out.
# The timeout period starts at IoTHubClient.send_event_async.
# By default, messages do not expire.
MESSAGE_TIMEOUT = 1000

RECEIVE_CONTEXT = 0
AVG_WIND_SPEED = 10.0
MIN_TEMPERATURE = 20.0
MIN_HUMIDITY = 60.0
MESSAGE_COUNT = 5
RECEIVED_COUNT = 0
TWIN_CONTEXT = 0
METHOD_CONTEXT = 0

# global counters
RECEIVE_CALLBACKS = 0
SEND_CALLBACKS = 0
BLOB_CALLBACKS = 0
TWIN_CALLBACKS = 0
SEND_REPORTED_STATE_CALLBACKS = 0
METHOD_CALLBACKS = 0

firstTime = True
hub_manager = None

PROTOCOL = IoTHubTransportProvider.MQTT
CONNECTION_STRING = "XXXXXX"

base_version = '1.0.0.000'
SUCCESS = 0
firstTime = True

def downloadImage(url):
    # Code for downloading the package from url
    return 0

def unzipPackage():
    #code for unzipping the package
    return 0

def readPackageData():
    # code reading package data
    return 0

def pre_install():
    #code for installing dependencies
    return 0

def install():
    #code for installing main package
    return 0

def post_install():
    #code for verifying installation 
    return 0


def start_software_update(url,message):
    global hub_manager
    print "Starting software update process!!!!"

    reported_state = "{\"updateStatus\":\"softwareUpdateinprogress\"}"
    hub_manager.send_reported_state(reported_state, len(reported_state), 1003)
    time.sleep(1)
    status = downloadImage(url)
    if status == SUCCESS:
        reported_state = "{\"updateStatus\":\"downloadComplete\"}"
        hub_manager.send_reported_state(reported_state, len(reported_state), 1004)
        print "Downlaod Phase Done!!!"
        time.sleep(1)
    else:
        print "Download Phase failed!!!!"
        return False
    status = unzipPackage()
    if status == SUCCESS:
        reported_state = "{\"updateStatus\":\"UnzipComplete\"}"
        hub_manager.send_reported_state(reported_state, len(reported_state), 1005)
        print "Unzip Package Done!!!"
        time.sleep(1)
    else:
        print "Unzip package failed!!!"
        return False
    status = readPackageData()
    if status == SUCCESS:
        reported_state = "{\"updateStatus\":\"ReadPackageData\"}"
        hub_manager.send_reported_state(reported_state, len(reported_state), 1006)
        print "Reading package json data"
        time.sleep(1)
    else:
        print "Failed Reading package!!!"
        return False
    status = pre_install()
    if status == SUCCESS:
        reported_state = "{\"updateStatus\":\"PreInstallComplete\"}"
        hub_manager.send_reported_state(reported_state, len(reported_state), 1007)
        time.sleep(1)
        print "pre_install state successful!!!"
    else:
        print "pre_install failed!!!!"
        return False
    status = install()
    if status == SUCCESS:   
        reported_state = "{\"updateStatus\":\"InstallComplete\"}"
        hub_manager.send_reported_state(reported_state, len(reported_state), 1008)
        time.sleep(1)
        print "install sucessful!!!"
    else:
        print "install failed!!!"
        return False
    status = post_install()
    if status == SUCCESS:   
        reported_state = "{\"updateStatus\":\"SoftwareUpdateComplete\"}"
        hub_manager.send_reported_state(reported_state, len(reported_state), 1009)
        time.sleep(1)
        print "post install sucessful!!!"
    else:
        print "post install failed!!!"
        return False
    return True


def device_twin_callback(update_state, payload, user_context):
    global TWIN_CALLBACKS
    global firstTime
    global base_version
    print ( "\nTwin callback called with:\nupdateStatus = %s\npayload = %s\ncontext = %s" % (update_state, payload, user_context) )
    TWIN_CALLBACKS += 1
    print ( "Total calls confirmed: %d\n" % TWIN_CALLBACKS )
    message = json.loads(payload)
    if not firstTime:
        if message["software_version"] != base_version:
            url = message["url"]
            status = start_software_update(url,message)
            if status:
                print "software Update Successful!!!"
            else:
                print "software Update Unsuccessful!!!"
    else:
        base_version = message["desired"]["software_version"]
        print "Set firstTime to false", base_version
        firstTime = False


def send_reported_state_callback(status_code, user_context):
    global SEND_REPORTED_STATE_CALLBACKS
    print ( "Confirmation for reported state received with:\nstatus_code = [%d]\ncontext = %s" % (status_code, user_context) )
    SEND_REPORTED_STATE_CALLBACKS += 1
    print ( "    Total calls confirmed: %d" % SEND_REPORTED_STATE_CALLBACKS )


class HubManager(object):

    def __init__(
            self,
            connection_string,
            protocol=IoTHubTransportProvider.MQTT):
        self.client_protocol = protocol
        self.client = IoTHubClient(connection_string, protocol)
        if protocol == IoTHubTransportProvider.HTTP:
            self.client.set_option("timeout", TIMEOUT)
            self.client.set_option("MinimumPollingTime", MINIMUM_POLLING_TIME)
        # set the time until a message times out
        self.client.set_option("messageTimeout", MESSAGE_TIMEOUT)
        # some embedded platforms need certificate information
        # self.set_certificates()
        self.client.set_device_twin_callback(device_twin_callback, TWIN_CONTEXT)



    def send_reported_state(self, reported_state, size, user_context):
        self.client.send_reported_state(
            reported_state, size,
            send_reported_state_callback, user_context)    

def main(connection_string, protocol):
    global hub_manager
    try:
        print ( "\nPython %s\n" % sys.version )
        print ( "IoT Hub Client for Python" )

        hub_manager = HubManager(connection_string, protocol)

        print ( "Starting the IoT Hub Python sample using protocol %s..." % hub_manager.client_protocol )
        reported_state = "{\"updateStatus\":\"waitingforupdate\"}"
        hub_manager.send_reported_state(reported_state, len(reported_state), 1002)

        while True:
            time.sleep(1)

    except IoTHubError as iothub_error:
        print ( "Unexpected error %s from IoTHub" % iothub_error )
        return
    except KeyboardInterrupt:
        print ( "IoTHubClient sample stopped" )

if __name__ == '__main__':
    try:
        (CONNECTION_STRING, PROTOCOL) = get_iothub_opt(sys.argv[1:], CONNECTION_STRING)
    except OptionError as option_error:
        print ( option_error )
        usage()
        sys.exit(1)

    main(CONNECTION_STRING, PROTOCOL)

Expected Result: The "reported" property for every stage in software update should update properly in device twin in azure portal.

Actual Result: The "reported" property for each stage in software update process is not updating properly.

cgoma
  • 47
  • 2
  • 13

0 Answers0