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.R;
|
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.NetworkUtils;
|
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<List<DeviceOidInfoBean>> 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<String>() {
|
@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<List<DeviceOidInfoBean>>() {
|
}.getType();
|
List<DeviceOidInfoBean> 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 oid 设备oid
|
* @param homeId 电站id
|
* @param callBack -
|
*/
|
public void getCurrentDeviceFirmwares(String deviceOidId, String oid, String homeId, CloudCallBeak<List<DeviceFirmwareBean>> callBack) {
|
String requestUrl = HttpApi.POST_OTA_GET_DeviceFirmwares;
|
JsonObject json = new JsonObject();
|
if (!TextUtils.isEmpty(deviceOidId)) {
|
json.addProperty("deviceOidId", deviceOidId);
|
} else {
|
json.addProperty("oid", oid);
|
}
|
json.addProperty("homeId", homeId);
|
HttpClient.getInstance().requestHttp(requestUrl, json.toString(), new CloudCallBeak<String>() {
|
@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<List<DeviceFirmwareBean>>() {
|
}.getType();
|
List<DeviceFirmwareBean> 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<List<CloudDeviceFirmwaresBean>> 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<String>() {
|
@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<List<CloudDeviceFirmwaresBean>>() {
|
}.getType();
|
List<CloudDeviceFirmwaresBean> 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<Boolean> 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<String>() {
|
@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 homeId 电站id
|
* @param callBack -
|
*/
|
public void getCurrentGatewayDrivers(String oid, String homeId, CloudCallBeak<List<GatewayDriverBean>> callBack) {
|
String requestUrl = HttpApi.POST_OTA_GET_GatewayDrivers;
|
JsonObject json = new JsonObject();
|
json.addProperty("homeId", homeId);
|
json.addProperty("oid", oid);
|
|
HttpClient.getInstance().requestHttp(requestUrl, json.toString(), new CloudCallBeak<String>() {
|
@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<List<GatewayDriverBean>>() {
|
}.getType();
|
List<GatewayDriverBean> 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<CloudGatewayDriversBean> 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<String>() {
|
@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<CloudGatewayDriversBean>() {
|
}.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<Boolean> 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<String>() {
|
@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<ResponseBody> callBack) {
|
HttpClient.getInstance().downLoadFile(downloadUrl, new CloudCallBeak<ResponseBody>() {
|
@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<String> 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<Boolean> 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(NetworkUtils.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, HDLApp.getInstance().getAppLocaleContext().getString(R.string.exception_unable_to_pull_up_the_cloud_upgrade_file_data));
|
return false;
|
}
|
if (TextUtils.isEmpty(md5)) {
|
this.eventBusPost(fileFullPath, driver, -101, HDLApp.getInstance().getAppLocaleContext().getString(R.string.exception_failed_to_obtain_the_md5_key_of_the_upgrade_file_on_the_cloud));
|
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, HDLApp.getInstance().getAppLocaleContext().getString(R.string.exception_unable_to_pull_up_the_cloud_upgrade_file_data));
|
return false;
|
}
|
fos = new FileOutputStream(file);
|
long sum = 0;
|
while ((len = is.read(buf)) != -1) {
|
if (this.stopDownload) {
|
this.eventBusPost(fileFullPath, driver, -108, HDLApp.getInstance().getAppLocaleContext().getString(R.string.exception_the_user_cancels_downloading_the_upgrade_file));
|
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);
|
}
|
}
|
fos.flush();
|
fos.close();
|
is.close();
|
byte[] bytes = HdlFileLogic.getInstance().readFileByte(fileFullPath);
|
// byte[] bytes = FileUtils.readFileToByteArray(file);//这个方法不兼用android 6.0
|
//todo 下载文件需要解密之后再进行md5去做比对
|
byte[] decrypt = AesUtils.decrypt(bytes);
|
if (decrypt == null) {
|
this.eventBusPost(fileFullPath, driver, -105, HDLApp.getInstance().getAppLocaleContext().getString(R.string.exception_failed_to_decrypt_the_upgrade_aes_file));
|
return false;
|
}
|
String fileMD5 = Md5Utils.encodeMD5(decrypt);
|
if (TextUtils.isEmpty(fileMD5)) {
|
this.eventBusPost(fileFullPath, driver, -106, HDLApp.getInstance().getAppLocaleContext().getString(R.string.exception_failed_to_generate_md5_for_the_upgrade_file));
|
return false;
|
}
|
if (!md5.equals(fileMD5)) {
|
this.eventBusPost(fileFullPath, driver, -107, HDLApp.getInstance().getAppLocaleContext().getString(R.string.exception_description_failed_to_compare_the_md5_of_the_upgrade_file));
|
return false;
|
}
|
//todo 注意:解密之后,要重新写数据;
|
HdlFileLogic.getInstance().writeFile(fileFullPath, decrypt);
|
// FileUtils.writeByteArrayToFile(file, decrypt, false);//这个方法不兼用android 6.0
|
this.eventBusPost(fileFullPath, driver, 100, HDLApp.getInstance().getAppLocaleContext().getString(R.string.exception_the_upgrade_file_is_downloaded));
|
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;
|
}
|
|
|
}
|