物联网设备进行OTA升级,需先在阿里云物联网平台为对应产品添加升级包。控制台操作流程请参考添加升级包。
如果希望通过API调用来完成升级包的上传,需按顺序依次调用物联网平台和对象存储OSS的多个接口。本文介绍具体的操作步骤并提供完整的Java代码示例。
准备工作
- 下载物联网平台云端SDK,最新版本请参考文档。
<!--https://mvnrepository.com/artifact/com.aliyun/iot20180120 --><dependency><groupId>com.aliyun</groupId><artifactId>iot20180120</artifactId><version>3.0.7</version></dependency><dependency><groupId>com.aliyun</groupId><artifactId>tea-openapi</artifactId><version>0.2.2</version></dependency>
- 下载对象存储OSS云端SDK,最新版本请参考文档。
<!--https://mvnrepository.com/artifact/com.aliyun.oss/aliyun-sdk-oss --><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.10.2</version></dependency>
操作步骤
调用GenerateOTAUploadURL接口生成升级包文件上传到对象存储(OSS)的信息。
本接口的返回参数包含:
- 第2步调用OSS PostObject上传升级包文件的请求参数:Key、OSSAccessKeyId、Signature和Policy。
- 第3步调用CreateOTAFirmware创建升级包的请求参数FirmwareUrl。
部分代码示例:
// GenerateOTAUploadURLcom.aliyun.iot20180120.Clientclient=OTAFirmware.createClient("LTAI4FvZ****", "biCR4vJnIq****"); GenerateOTAUploadURLRequestgenerateOTAUploadURLRequest=newGenerateOTAUploadURLRequest() .setIotInstanceId("iot-******") .setFileSuffix("zip"); RuntimeOptionsruntime=newRuntimeOptions(); GenerateOTAUploadURLResponsegenerateOTAUploadURLResponse=client.generateOTAUploadURLWithOptions(generateOTAUploadURLRequest, runtime); // 获取OSS表单上传的参数信息StringKey=generateOTAUploadURLResponse.body.data.key; StringOSSAccessKeyId=generateOTAUploadURLResponse.body.data.OSSAccessKeyId; StringSignature=generateOTAUploadURLResponse.body.data.signature; StringPolicy=generateOTAUploadURLResponse.body.data.policy; StringHost=generateOTAUploadURLResponse.body.data.host; // 获取IoT创建升级包的urlStringFirmwareUrl=generateOTAUploadURLResponse.body.data.firmwareUrl;
- 调用PostObject接口
在第1步的GenerateOTAUploadURL接口返回结果后的1分钟之内,使用OSS的PostObject接口上传升级包文件。
说明 GenerateOTAUploadURL接口返回的参数信息有效期为1分钟,请在1分钟内上传升级包。上传的升级包文件大小不能超过2,000 MB。
部分代码示例:
//待上传的本地升级包路径StringlocalFilePath="D:\****\test.zip"; // PostObjectPostObject(Key, Host, Policy, OSSAccessKeyId, Signature, localFilePath);
升级包上传完成后,请在60分钟内,调用物联网平台APICreateOTAFirmware接口创建升级包。
如果上传了升级包,但未调用CreateOTAFirmware接口创建升级包,上传的文件将被系统定期自动清理。
部分代码示例:
// CreateOTAFirmwareCreateOTAFirmwareRequestcreateOTAFirmwareRequest=newCreateOTAFirmwareRequest() .setIotInstanceId("iot-****") .setFirmwareName("API上传固件测试") .setDestVersion("1.0") .setFirmwareUrl(FirmwareUrl) .setProductKey("g8orC****"); CreateOTAFirmwareResponsecreateOTAFirmwareResponse=client.createOTAFirmwareWithOptions(createOTAFirmwareRequest, runtime);
注意事项
- 上述API接口的完整请求参数、返回数据说明,请到产品API列表中,点击API查看详情,本文不做过多描述。
- 目前OSS SDK中,仅Java SDK提供了PostObject接口上传示例。如需使用其他开发语言,请自行参考API文档完成表单上传操作。
完整代码示例
importcom.aliyun.iot20180120.models.*; importcom.aliyun.teaopenapi.models.*; importcom.aliyun.teautil.models.*; importjavax.activation.MimetypesFileTypeMap; importjava.io.*; importjava.net.HttpURLConnection; importjava.net.URL; importjava.util.Iterator; importjava.util.LinkedHashMap; importjava.util.Map; importcom.aliyun.oss.ClientException; publicclassOTAFirmware { publicstaticcom.aliyun.iot20180120.ClientcreateClient(StringaccessKeyId, StringaccessKeySecret) throwsException { Configconfig=newConfig() .setAccessKeyId(accessKeyId) .setAccessKeySecret(accessKeySecret); config.endpoint="iot.cn-shanghai.aliyuncs.com"; returnnewcom.aliyun.iot20180120.Client(config); } publicstaticvoidmain(String[] args) throwsException { // GenerateOTAUploadURLcom.aliyun.iot20180120.Clientclient=OTAFirmware.createClient("LTAI4FvZ8****", "biCR4vJnIqi48****"); GenerateOTAUploadURLRequestgenerateOTAUploadURLRequest=newGenerateOTAUploadURLRequest() .setIotInstanceId("iot-****") .setFileSuffix("zip"); RuntimeOptionsruntime=newRuntimeOptions(); GenerateOTAUploadURLResponsegenerateOTAUploadURLResponse=client.generateOTAUploadURLWithOptions(generateOTAUploadURLRequest, runtime); // 获取OSS表单上传的参数信息StringKey=generateOTAUploadURLResponse.body.data.key; StringOSSAccessKeyId=generateOTAUploadURLResponse.body.data.OSSAccessKeyId; StringSignature=generateOTAUploadURLResponse.body.data.signature; StringPolicy=generateOTAUploadURLResponse.body.data.policy; StringHost=generateOTAUploadURLResponse.body.data.host; // 获取IoT创建升级包的urlStringFirmwareUrl=generateOTAUploadURLResponse.body.data.firmwareUrl; //待上传的本地升级包路径StringlocalFilePath="D:\****\test.zip"; // PostObjectPostObject(Key, Host, Policy, OSSAccessKeyId, Signature, localFilePath); // CreateOTAFirmwareCreateOTAFirmwareRequestcreateOTAFirmwareRequest=newCreateOTAFirmwareRequest() .setIotInstanceId("iot-****") .setFirmwareName("API上传固件测试") .setDestVersion("1.0") .setFirmwareUrl(FirmwareUrl) .setProductKey("g8or****"); CreateOTAFirmwareResponsecreateOTAFirmwareResponse=client.createOTAFirmwareWithOptions(createOTAFirmwareRequest, runtime); System.out.println("Success is: "+createOTAFirmwareResponse.body.success); System.out.println("requestID is: "+createOTAFirmwareResponse.body.requestId); System.out.println("FirmwareId is: "+createOTAFirmwareResponse.body.data.firmwareId); } privatestaticvoidPostObject(Stringkey, Stringhost, Stringpolicy, StringaccessKeyId, Stringsignature, StringlocalFilePath) throwsException { StringurlStr=host; // 设置表单Map。Map<String, String>formFields=newLinkedHashMap<String, String>(); formFields.put("key", key); formFields.put("Content-Disposition", "attachment;filename="+localFilePath); formFields.put("OSSAccessKeyId", accessKeyId); formFields.put("policy", policy); formFields.put("Signature", signature); Stringret=formUpload(urlStr, formFields, localFilePath); System.out.println("Post Object to OSS success"); } privatestaticStringformUpload(StringurlStr, Map<String, String>formFields, StringlocalFile) throwsException { Stringres=""; HttpURLConnectionconn=null; Stringboundary="9431149156168"; try { URLurl=newURL(urlStr); conn= (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setReadTimeout(30000); conn.setDoOutput(true); conn.setDoInput(true); conn.setRequestMethod("POST"); conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)"); // 设置MD5值。MD5值由整个Body计算得出。如果希望开启MD5校验,可参考MD5加密设置。// conn.setRequestProperty("Content-MD5", contentMD5);conn.setRequestProperty("Content-Type", "multipart/form-data; boundary="+boundary); OutputStreamout=newDataOutputStream(conn.getOutputStream()); // 遍历读取表单Map中的数据,将数据写入到输出流中。if (formFields!=null) { StringBufferstrBuf=newStringBuffer(); Iterator<Map.Entry<String, String>>iter=formFields.entrySet().iterator(); inti=0; while (iter.hasNext()) { Map.Entry<String, String>entry=iter.next(); StringinputName=entry.getKey(); StringinputValue=entry.getValue(); if (inputValue==null) { continue; } if (i==0) { strBuf.append("--").append(boundary).append("\r\n"); strBuf.append("Content-Disposition: form-data; name=\""+inputName+"\"\r\n\r\n"); strBuf.append(inputValue); } else { strBuf.append("\r\n").append("--").append(boundary).append("\r\n"); strBuf.append("Content-Disposition: form-data; name=\""+inputName+"\"\r\n\r\n"); strBuf.append(inputValue); } i++; } out.write(strBuf.toString().getBytes()); } // 读取文件信息,将要上传的文件写入到输出流中。Filefile=newFile(localFile); Stringfilename=file.getName(); StringcontentType=newMimetypesFileTypeMap().getContentType(file); if (contentType==null||contentType.equals("")) { contentType="application/octet-stream"; } StringBufferstrBuf=newStringBuffer(); strBuf.append("\r\n").append("--").append(boundary) .append("\r\n"); strBuf.append("Content-Disposition: form-data; name=\"file\"; "+"filename=\""+filename+"\"\r\n"); strBuf.append("Content-Type: "+contentType+"\r\n\r\n"); out.write(strBuf.toString().getBytes()); DataInputStreamin=newDataInputStream(newFileInputStream(file)); intbytes=0; byte[] bufferOut=newbyte[1024]; while ((bytes=in.read(bufferOut)) !=-1) { out.write(bufferOut, 0, bytes); } in.close(); byte[] endData= ("\r\n--"+boundary+"--\r\n").getBytes(); out.write(endData); out.flush(); out.close(); // 读取返回数据。strBuf=newStringBuffer(); BufferedReaderreader=newBufferedReader(newInputStreamReader(conn.getInputStream())); Stringline=null; while ((line=reader.readLine()) !=null) { strBuf.append(line).append("\n"); } res=strBuf.toString(); reader.close(); reader=null; } catch (ClientExceptione) { // System.err.println("Send post request exception: " + e);System.err.println(e.getErrorCode()+" msg="+e.getMessage()); throwe; } finally { if (conn!=null) { conn.disconnect(); conn=null; } } returnres; } }
运行结果
在控制台的监控运维-OTA升级的升级包列表中,可以看到上传成功的升级包。