package com.hdl.photovoltaic.other; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.text.TextUtils; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; import com.hdl.linkpm.sdk.core.exception.HDLException; import com.hdl.linkpm.sdk.device.bean.DeviceOidInfoBean; import com.hdl.linkpm.sdk.ota.bean.CloudDeviceFirmwaresBean; import com.hdl.linkpm.sdk.ota.bean.CloudGatewayDriversBean; import com.hdl.linkpm.sdk.ota.bean.DeviceFirmwareBean; import com.hdl.linkpm.sdk.ota.bean.GatewayDriverBean; import com.hdl.photovoltaic.HDLApp; import com.hdl.photovoltaic.config.UserConfigManage; import com.hdl.photovoltaic.internet.HttpClient; import com.hdl.photovoltaic.internet.HttpServer.MyNanoHttpServer; import com.hdl.photovoltaic.internet.HttpServer.MyNanoHttpService; import com.hdl.photovoltaic.internet.TcpClient; import com.hdl.photovoltaic.internet.api.HttpApi; import com.hdl.photovoltaic.internet.api.TopicApi; import com.hdl.photovoltaic.listener.CloudCallBeak; import com.hdl.photovoltaic.listener.LinkCallBack; import com.hdl.photovoltaic.utils.AesUtils; import com.hdl.photovoltaic.utils.Md5Utils; import com.hdl.photovoltaic.utils.NetworkUtils123; import com.hdl.sdk.link.common.exception.HDLLinkException; import com.hdl.sdk.link.core.bean.eventbus.BaseEventBus; import com.hdl.sdk.link.core.callback.HDLLinkCallBack; import org.apache.commons.io.FileUtils; import org.greenrobot.eventbus.EventBus; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import okhttp3.ResponseBody; /** * ota升级逻辑 */ public class HdlOtaLogic { private static volatile HdlOtaLogic sHdlOtaLogic; /** * 获取当前对象 * * @return HdlDeviceLogic */ public static synchronized HdlOtaLogic getInstance() { if (sHdlOtaLogic == null) { synchronized (HdlOtaLogic.class) { if (sHdlOtaLogic == null) { sHdlOtaLogic = new HdlOtaLogic(); } } } return sHdlOtaLogic; } /** * Intent专门启动本地服务 * * @return Intent */ public Intent getIntent() { return intentServer; } public void setIntent(Intent intent) { this.intentServer = intent; } private Intent intentServer = null; private ServiceConnection mServiceConnection = null; /** * 服务是否开启 true=开启 */ public boolean mServiceStart = false; /** * true表示终止下载升级文件(用户行为) */ private boolean stopDownload = false; //region -----固件升级--------- /** * 向云端获取逆变器oid列表 * 前提条件:要上传逆变器oid列表给云端 * * @param callBack - */ public void getCloudOidList(CloudCallBeak> callBack) { String requestUrl = HttpApi.POST_DEVICE_OID_LIST_GET; JsonObject json = new JsonObject(); json.addProperty("homeId", UserConfigManage.getInstance().getHomeId()); HttpClient.getInstance().requestHttp(requestUrl, json.toString(), new CloudCallBeak() { @Override public void onSuccess(String json) { if (TextUtils.isEmpty(json)) { if (callBack != null) { callBack.onSuccess(new ArrayList<>()); } return; } Gson gson = new Gson(); Type typeOfT = new TypeToken>() { }.getType(); List list = gson.fromJson(json, typeOfT); if (callBack != null) { callBack.onSuccess(list); } } @Override public void onFailure(HDLException e) { if (callBack != null) { callBack.onFailure(e); } } }); } /** * 向云端获取【当前设备固件】列表 * 前提条件:设备自动上报oid信息给云端 * * @param deviceOidId oid云端id * @param callBack - */ public void getCurrentDeviceFirmwares(String deviceOidId, CloudCallBeak> callBack) { String requestUrl = HttpApi.POST_OTA_GET_DeviceFirmwares; JsonObject json = new JsonObject(); json.addProperty("deviceOidId", deviceOidId); json.addProperty("homeId", UserConfigManage.getInstance().getHomeId()); HttpClient.getInstance().requestHttp(requestUrl, json.toString(), new CloudCallBeak() { @Override public void onSuccess(String json) { if (TextUtils.isEmpty(json)) { if (callBack != null) { callBack.onSuccess(new ArrayList<>()); } return; } Gson gson = new Gson(); Type typeOfT = new TypeToken>() { }.getType(); List list = gson.fromJson(json, typeOfT); if (callBack != null) { callBack.onSuccess(list); } } @Override public void onFailure(HDLException e) { if (callBack != null) { callBack.onFailure(e); } } }); } /** * 向云端获取【设备新固件】列表 * 前提条件:要通过平台软件上传新固件 * * @param hardwareModel 硬件型号 * @param osImageId 系统镜像id * @param callBack - */ public void getNewDeviceFirmwares(String hardwareModel, String osImageId, CloudCallBeak> callBack) { String requestUrl = HttpApi.POST_OTA_GET_CloudDeviceFirmwares; JsonObject json = new JsonObject(); json.addProperty("hardwareModel", hardwareModel); json.addProperty("osImageId", osImageId); // json.addProperty("protocolType", "ZIGBEE");//协议类型,可用值:BUSPRO,KNX,ZIGBEE,OTHER HttpClient.getInstance().requestHttp(requestUrl, json.toString(), new CloudCallBeak() { @Override public void onSuccess(String json) { if (TextUtils.isEmpty(json)) { if (callBack != null) { callBack.onSuccess(new ArrayList<>()); } return; } Gson gson = new Gson(); Type typeOfT = new TypeToken>() { }.getType(); List list = gson.fromJson(json, typeOfT); if (callBack != null) { callBack.onSuccess(list); } } @Override public void onFailure(HDLException e) { if (callBack != null) { callBack.onFailure(e); } } }); } /** * 向云端发起【设备固件】升级OTA指令 * * @param deviceOidId 设备id * @param firmwareVersionId 固件版本id * @param callBack- */ public void upgradeDeviceFirmware(String deviceOidId, String firmwareVersionId, CloudCallBeak callBack) { String requestUrl = HttpApi.POST_OTA_DeviceFirmwareUpgrade; JsonObject json = new JsonObject(); json.addProperty("homeId", UserConfigManage.getInstance().getHomeId()); json.addProperty("deviceOidId", deviceOidId); json.addProperty("firmwareVersionId", firmwareVersionId); HttpClient.getInstance().requestHttp(requestUrl, json.toString(), new CloudCallBeak() { @Override public void onSuccess(String json) { if (callBack != null) { callBack.onSuccess(true); } } @Override public void onFailure(HDLException e) { if (callBack != null) { callBack.onFailure(e); } } }); } //endregion //region -----驱动升级--------- /** * 向云端获取【当前设备驱动】列表 * 前提条件:设备自动上报oid信息给云端 * * @param oid 网关设备oid * @param callBack - */ public void getCurrentGatewayDrivers(String oid, CloudCallBeak> callBack) { String requestUrl = HttpApi.POST_OTA_GET_GatewayDrivers; JsonObject json = new JsonObject(); json.addProperty("homeId", UserConfigManage.getInstance().getHomeId()); json.addProperty("oid", oid); HttpClient.getInstance().requestHttp(requestUrl, json.toString(), new CloudCallBeak() { @Override public void onSuccess(String json) { if (TextUtils.isEmpty(json)) { if (callBack != null) { callBack.onSuccess(new ArrayList<>()); } return; } Gson gson = new Gson(); Type typeOfT = new TypeToken>() { }.getType(); List list = gson.fromJson(json, typeOfT); if (callBack != null) { callBack.onSuccess(list); } } @Override public void onFailure(HDLException e) { if (callBack != null) { callBack.onFailure(e); } } }); } /** * 向云端获取【设备新驱动】列表 * 前提条件:要通过平台软件上传新驱动 * * @param driveCode 驱动编号或驱动名称 * @param osImageId 驱动类型id * @param callBack - */ public void getNewGatewayDrivers(String driveCode, String osImageId, CloudCallBeak callBack) { String requestUrl = HttpApi.POST_OTA_GET_CloudGatewayDrivers; JsonObject json = new JsonObject(); json.addProperty("driveCode", driveCode); json.addProperty("osImageId", osImageId); HttpClient.getInstance().requestHttp(requestUrl, json.toString(), new CloudCallBeak() { @Override public void onSuccess(String json) { if (TextUtils.isEmpty(json)) { if (callBack != null) { callBack.onSuccess(new CloudGatewayDriversBean()); } return; } Gson gson = new Gson(); Type typeOfT = new TypeToken() { }.getType(); CloudGatewayDriversBean cloudGatewayDriversBean = gson.fromJson(json, typeOfT); if (callBack != null) { callBack.onSuccess(cloudGatewayDriversBean); } } @Override public void onFailure(HDLException e) { if (callBack != null) { callBack.onFailure(e); } } }); } /** * 云端发起【设备驱动升级】OTA指令 * * @param oid 网关设备oid * @param driverVersionId 驱动版本id * @param callBack - */ public void upgradeGatewayDriver(String oid, String driverVersionId, CloudCallBeak callBack) { String requestUrl = HttpApi.POST_OTA_GatewayDriverUpgrade; JsonObject json = new JsonObject(); json.addProperty("homeId", UserConfigManage.getInstance().getHomeId()); json.addProperty("oid", oid); json.addProperty("driverVersionId", driverVersionId); HttpClient.getInstance().requestHttp(requestUrl, json.toString(), new CloudCallBeak() { @Override public void onSuccess(String json) { if (callBack != null) { callBack.onSuccess(true); } } @Override public void onFailure(HDLException e) { if (callBack != null) { callBack.onFailure(e); } } }); } //endregion /** * 取消终止下载文件指令 */ public void stopDownloadUpgradeFile() { this.stopDownload = true; } /** * 向云端获取【设备升级文件(驱动,固件)下载】升级文件 * * @param downloadUrl 云端驱动地址 */ public void getDeviceUpgradeDownloadFile(String downloadUrl, CloudCallBeak callBack) { HttpClient.getInstance().downLoadFile(downloadUrl, new CloudCallBeak() { @Override public void onSuccess(ResponseBody s) { if (callBack != null) { callBack.onSuccess(s); } } @Override public void onFailure(HDLException e) { if (callBack != null) { callBack.onFailure(e); } } }); } /** * 本地升级包推送(告诉网关下载升级包地址等信息) * * @param mac 物理设备mac * @param oid 物理设备oid * @param module 模块信息 * @param version 版本号 * @param size 升级包大小 * @param url 升级包下载地址(存储在本地) * @param sign_method md5加密字符串 * @param linkCallBack - */ public void pushUpgradePacketInfo(String mac, String oid, String module, String version, String size, String url, String sign_method, LinkCallBack linkCallBack) { String requestUrl = TopicApi.SET_GATEWAY_UPGRADE_INFO; JsonArray jsonArray = new JsonArray(); JsonObject json = new JsonObject(); json.addProperty("oid", oid);// 物理设备oid json.addProperty("module", module);//模块信息 json.addProperty("version", version);//版本号 // json.addProperty("is_diff", is_diff);//true=增量包,false=全量包 json.addProperty("size", size);//升级包大小 json.addProperty("url", url);//升级包下载地址 json.addProperty("sign", sign_method);//升级包签名类型:md5 json.addProperty("sign_method", "md5");//升级包签名类型:md5 jsonArray.add(json); TcpClient.getInstance().sendDataToLinkGateway(mac, requestUrl, jsonArray, "", new HDLLinkCallBack() { @Override public void onSuccess(String msg) { if (linkCallBack != null) { linkCallBack.onSuccess(msg); } } @Override public void onError(HDLLinkException e) { if (linkCallBack != null) { linkCallBack.onError(e); } } }); } /** * 取消升级驱动,固件文件指令 * * @param mac 设备mac * @param linkCallBack 回调update */ public void cancelUpgrade(String mac, LinkCallBack linkCallBack) { String requestUrl = TopicApi.SET_GATEWAY_REMOTE_EDIT; // JsonObject json = new JsonObject(); // json.addProperty("homeId", UserConfigManage.getInstance().getHomeId()); // json.addProperty("server_addr", AppConfigManage.getUserRegionUrl()); // json.addProperty("local_secret", UserConfigManage.getInstance().getLocalSecret()); // //解密负载数据(写密钥给网关一定是明文,因为那时网关还没有密钥) // TcpClient.getInstance().sendDataToLinkGateway(mac, false, requestUrl, json, "", new HDLLinkCallBack() { // @Override // public void onSuccess(String msg) { // GatewayBean gatewayBean = HDLLinkLocalGateway.getInstance().getLocalGateway(mac); // if (gatewayBean != null) { // if (!TextUtils.isEmpty(UserConfigManage.getInstance().getLocalSecret())) { // gatewayBean.setLocalEncrypt(true); // } // } // if (linkCallBack != null) { // linkCallBack.onSuccess(true); // } // // } // // @Override // public void onError(HDLLinkException e) { // if (linkCallBack != null) { // linkCallBack.onError(e); // } // } // }); } /** * 启动本地服务 */ public void startLocalService(ServiceConnection serviceConnection) { //本地 //1,建立本地服务; //2,告诉网关手机ip和端口; //实例化 获取ip 地址 MyNanoHttpServer.getInstance(NetworkUtils123.getInstance().getIPAddress(HDLApp.getInstance())); //MyNanoHttpServer.getInstance("127.0.0.1"); intentServer = new Intent(); intentServer.setClass(HDLApp.getInstance(), MyNanoHttpService.class); this.mServiceConnection = serviceConnection; this.mServiceStart = true; //启动服务监听 HDLApp.getInstance().bindService(intentServer, serviceConnection, Context.BIND_AUTO_CREATE); } /** * 关闭本地服务 */ public void unLocalService() { if (intentServer != null && this.mServiceConnection != null) { HDLApp.getInstance().unbindService(this.mServiceConnection); this.mServiceStart = false; } } /** * 处理下载文件数据 * * @param fileFullPath 文件全路径 * @param zipData 文件数据流对象 * @param md5 检验文件MD5值 * @param driver 驱动或者固件 * @return 成功true */ public boolean disposeDownLoadFile(String fileFullPath, ResponseBody zipData, String md5, String driver) { this.stopDownload = false; //-100:没有数据;-101:没有md5秘钥;-102:md5秘钥不对;-103:有异常; if (zipData == null) { this.eventBusPost(fileFullPath, driver, -100, "拉不到云端升级文件数据"); HdlLogLogic.print("拉不到云端升级文件数据(-100)", true); return false; } if (TextUtils.isEmpty(md5)) { this.eventBusPost(fileFullPath, driver, -101, "拿不到云端上升级文件md5秘钥"); HdlLogLogic.print("拿不到云端上升级文件md5秘钥(-101)", true); return false; } InputStream is = null; byte[] buf = new byte[1204 * 4]; int len = 0; FileOutputStream fos = null; File file = null; try { file = new File(fileFullPath); is = zipData.byteStream(); long total = zipData.contentLength(); if (total == 0) { this.eventBusPost(fileFullPath, driver, -102, "拉不到云端升级文件数据"); HdlLogLogic.print("拉不到云端升级文件数据(-102)", true); return false; } fos = new FileOutputStream(file); long sum = 0; while ((len = is.read(buf)) != -1) { if (this.stopDownload) { this.eventBusPost(fileFullPath, driver, -108, "用户取消下载升级文件."); HdlLogLogic.print("用户取消下载升级文件(-108)", true); fos.flush(); fos.close(); is.close(); //todo 用户终止继续读取数据; return false; } fos.write(buf, 0, len); sum += len; //todo 下载中,可以自己计算的进度条(可以广播出去) int progress = (int) (100 * sum * 1.0f / total); if (sum != total) { //不等于100都要报,等于100处理整块逻辑完之后再报100; this.eventBusPost(fileFullPath, driver, progress, "正常上报进度值->" + progress); HdlLogLogic.print("正常上报进度值->" + progress, true); } } fos.flush(); fos.close(); is.close(); byte[] bytes = FileUtils.readFileToByteArray(file); //下载文件需要解密之后再进行md5去做比对 byte[] decrypt = AesUtils.decrypt(bytes); if (decrypt == null) { this.eventBusPost(fileFullPath, driver, -105, "升级文件aes解密失败."); HdlLogLogic.print("升级文件aes解密失败(-105)", true); return false; } String fileMD5 = Md5Utils.encodeMD5(decrypt); if (TextUtils.isEmpty(fileMD5)) { this.eventBusPost(fileFullPath, driver, -106, "升级文件生成md5失败失败."); HdlLogLogic.print("升级文件生成md5失败失败(-106)", true); return false; } if (!md5.equals(fileMD5)) { this.eventBusPost(fileFullPath, driver, -107, "升级文件md5比对失败."); HdlLogLogic.print("升级文件md5比对失败(-107)", true); return false; } //todo 注意:解密之后,要重新写数据; FileUtils.writeByteArrayToFile(file, decrypt, false); this.eventBusPost(fileFullPath, driver, 100, "升级文件下载完成."); HdlLogLogic.print("升级文件下载完成.", true); return true; } catch (Exception e) { this.eventBusPost(fileFullPath, driver, -103, e.getMessage()); e.printStackTrace(); } return false; } /** * 发布进度主题 * * @param type 驱动:driver,固件:firmware * @param progressValue 进度值 * @param describe 描述文本 */ public void eventBusPost(String fileFullPath, String type, int progressValue, String describe) { if (this.stopDownload) { // HdlFileLogic.getInstance().deleteFile(fileFullPath);//删除下载不完整数据; //取消下载广播一次 BaseEventBus baseEventBus = new BaseEventBus(); baseEventBus.setTopic(localDownloadProgress); Progress progress = new Progress(); progress.step = -108; progress.describe = describe; baseEventBus.setType(type); baseEventBus.setData(progress); EventBus.getDefault().post(baseEventBus); return; } // HdlThreadLogic.runMainThread(new Runnable() { // @Override // public void run() { BaseEventBus baseEventBus = new BaseEventBus(); baseEventBus.setTopic(localDownloadProgress); Progress progress = new Progress(); progress.step = progressValue; progress.describe = describe; progress.type = type; baseEventBus.setType(type); baseEventBus.setData(progress); EventBus.getDefault().post(baseEventBus); // } // }); } //自定义上报下载驱动或固件进度主题 public static final String localDownloadProgress = "cloud/download/progress/up"; public static final String driver_type = "driver"; public static final String firmware_type = "firmware"; public static class Progress { //进度值 public int step; //进度描述信息 public String describe; //表示是驱动,固件; public String type; } }