要求设备获取新软件,对自身进行更新并确认完成。
IoT 解决方案需要为设备提供更新自己软件的机制。无需人工干预的软件更新的支持,对于将解决方案扩展到数百万台设备以及提供出色的客户体验都是至关重要。然而,以安全、可扩展和可靠的方式实现大量设备的全量更新需要可扩展以满足设备负载的解决方案、弹性的命令机制以及可以跟踪整个设备组状态的方法。
利用“命令”和“设备状态副本”设计的 IoT 解决方案,加上一个全球可用且可扩展的存储解决方案,足以应对大量设备进行软件更新时所带来的所有挑战。
如下图所示的软件更新的模式可以提供这样的功能。

state/deviceID/update/delta 并从设备状态副本接收到设备相关的状态变化消息。state/deviceID/update发布一条期望状态消息。该消息包含一个软件更新的 URL,该 URL 与设备当前软件版本的 URL 是不同的state/deviceID/update/delta发布一条差异消息,该消息会被发送到设备。state/deviceID/update发布一条确认消息,反馈设备当前所使用的软件版本。追踪该设备的软件状态副本会将新状态记录在一个持久化数据存储中。state/deviceID/update/accepted发布一条消息,确认软件更新已经完成。当实现这个设计时,请考虑如下问题:
通过使用预签名 URL或者临时凭证,解决方案可以确保只有需要进行软件更新的目标设备才能获取软件更新包。这两种方法有不同的考虑点。
预签名 URL - 预签名 URL 的好处是它能够限制设备只能在一段时间内进行软件更新,或是设备需要有特定公共 IP 地址才能下载软件更新。当下载软件更新包的设备没有可公开解析的 IP 地址时,这种方法的不利之处就会显现出来。如果没有公开可解析的 IP 地址,解决方案只能在软件更新上设置时间限制。解决方案的实践者可能会或者可能不会认为这是可接受的。
临时凭证 - 设备与解决方案进行交互,以获取一个仅有存储访问权限的临时凭证以便下载软件更新。使用临时凭证的好处是只有拥有该凭证的设备才能访问软件更新,即使该设备没有可公开解析的 IP 地址也是如此。这种方法稍微不好的地方在于设备和解决方案会变得更加复杂,因为设备需要经过一个单独的流程来获取临时凭证。
设备在 IoT 解决方案中通过设备状态副本获取并执行“更新”命令的逻辑示例如下。具体而言,设备将获得新软件,使用该软件执行更新,并确认完成。
设备通过订阅一个消息监听函数,处理来自state/deviceID/update/delta主题的命令消息
def message_listener(message):
# ..do something with 'message'..
def main():
# subscribe the message listener function to the topic
sub = topic_subscribe('state/deviceID/update/delta', message_listener)
# now wait until the program should end
wait_until_exit()
过了一段时间后,设备收到一个差异消息,该消息是’软件更新’命令消息
def message_listener(message):
# parse the message from raw format into something the program can use
msg = parse_message(message)
# determine if the message is an update command type
if msg is UPDATE_COMMAND:
# get the globally unique job ID from the command message
job_id = msg.get_job_id()
# read the software update URL from the command message
url = msg.read_value('softwareURL')
# download the software from the given URL
software = download_software(url)
# ..and apply the software update triggered by the specific job ID
apply_software(software, job_id)
设备执行更新并将执行更新的结果发布到state/deviceID/update主题上以完成对命令的确认
def apply_software(software, job_id):
# do the local, device-specific work to apply the software
# and produce a result value of SUCCESS or FAILURE
if result is SUCCESS:
# make a success message
message = 'jobID:' + job_id + " SUCCESS"
else:
#make a failure message
message = 'jobID:' + job_id + "FAILURE"
# the topic used to publish the acknowledge message
topic = 'state/deviceID/update'
# ...and finally, publish the acknowledge message
message_publish(topic, message, quality_of_service)