Commit f022264b by pye52

Merge branch 'master' into rel-1.3.6

parents 002c8477 4189ff05
package com.bgycc.smartcanteen.command;
import androidx.work.BackoffPolicy;
import androidx.work.Data;
import androidx.work.ListenableWorker;
import androidx.work.OneTimeWorkRequest;
......@@ -9,6 +10,7 @@ import com.google.gson.Gson;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public class CommandHelper {
private static final String LOG_UPLOAD = "LOG_PULL";
......@@ -72,6 +74,11 @@ public class CommandHelper {
worker = new OneTimeWorkRequest.Builder(workerClass)
.setInputData(inputData)
.addTag(command.getAction())
.setBackoffCriteria(
BackoffPolicy.LINEAR,
OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS
)
.build();
}
return worker;
......
......@@ -8,6 +8,7 @@ import androidx.work.WorkerParameters;
import com.bgycc.smartcanteen.api.SCApi;
import com.bgycc.smartcanteen.api.SCRetrofit;
import com.bgycc.smartcanteen.entity.CommandLog;
import com.bgycc.smartcanteen.utils.DeviceProxy;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.PathUtils;
......@@ -40,6 +41,8 @@ public class LogCommandWorker extends CommandWorker {
private static final String ZIP_FILE = "log.zip";
private static final String UPLOAD_DIR = "upload_log";
private static final long DEFAULT_DELAY = 1000;
// 上传失败时最多重试次数
private static final int MAX_RETRY_TIMES = 3;
private SimpleDateFormat parseFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
private SimpleDateFormat nameFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
......@@ -62,12 +65,21 @@ public class LogCommandWorker extends CommandWorker {
return failed("日志上传指令不符合规范");
}
File logFile = getZipLogs();
if (logFile != null) {
inProgress("上传压缩文件至服务器");
upload(logFile);
if (logFile == null) {
return failed();
}
inProgress("上传压缩文件至服务器");
if (upload(logFile)) {
return success();
}
return failed();
int attemptCount = getRunAttemptCount();
// 检查该任务的重试次数,若未超过限制,则重试
if (attemptCount >= MAX_RETRY_TIMES) {
LogUtils.w(TAG, "超过重试限制,该上传任务失败");
return failed();
}
LogUtils.w(TAG, "上传失败,当前重试次数: " + attemptCount);
return Result.retry();
}
private void parseDate() {
......@@ -106,8 +118,17 @@ public class LogCommandWorker extends CommandWorker {
}
if (uploadDir == null) return null;
if (!copyTargetFiles(logDir, uploadDir)) {
LogUtils.d(TAG, "没有匹配的日志文件");
try {
if (!copyTargetFiles(logDir, uploadDir)) {
LogUtils.d(TAG, "日志文件筛选出错");
FileUtils.delete(uploadDir);
uploadDir = null;
return null;
}
} catch (Exception e) {
LogUtils.e(TAG, "日志文件复制出错: " + e.getMessage(), e);
FileUtils.delete(uploadDir);
uploadDir = null;
return null;
}
......@@ -132,7 +153,7 @@ public class LogCommandWorker extends CommandWorker {
private File getLogDirByType(String logType) {
File logDir;
if (logType.equals(BOOT_LOG)) {
logDir = new File(PathUtils.getExternalStoragePath(), "boot_log");
logDir = new File(DeviceProxy.getSystemLogDir());
} else {
logDir = new File(LogUtils.getConfig().getDir());
}
......@@ -161,6 +182,9 @@ public class LogCommandWorker extends CommandWorker {
return date.after(startTime) && date.before(endTime);
};
List<File> logFiles = FileUtils.listFilesInDirWithFilter(src, filter, false, null);
if (logFiles.isEmpty()) {
return true;
}
boolean copyResult = true;
inProgress("筛选目标日志文件");
int count = 0;
......@@ -173,10 +197,10 @@ public class LogCommandWorker extends CommandWorker {
if (tempCopyResult) count++;
}
LogUtils.d(TAG, "待上传日志文件总数: " + logFiles.size() + ", 复制成功文件总数: " + count);
return !logFiles.isEmpty() && copyResult;
return copyResult;
}
private void upload(File zip) {
private boolean upload(File zip) {
OkHttpClient client = SCRetrofit.createOkHttpClientBuilder().build();
SCApi api = SCRetrofit.createApi(client);
CommandLog.CommandLogData data = commandLog.getData();
......@@ -190,9 +214,11 @@ public class LogCommandWorker extends CommandWorker {
MultipartBody.Part body = MultipartBody.Part.createFormData("file", fileNameForServer, requestBody);
try {
Response<String> response = api.upload(body).execute();
LogUtils.d(TAG, "日志文件上传成功: " + response);
LogUtils.d(TAG, "日志文件上传完毕: " + response);
return response.isSuccessful();
} catch (IOException e) {
LogUtils.e(TAG, "日志文件上传失败: " + e.getMessage());
return false;
} finally {
FileUtils.delete(uploadDir);
FileUtils.delete(zip);
......
package com.bgycc.smartcanteen.entity;
import java.util.Objects;
public class CheckDevice {
private String action;
private CheckDeviceData data;
private long serialNumber;
public CheckDevice(String action, String deviceSN) {
this.action = action;
this.data = new CheckDeviceData(deviceSN);
this.serialNumber = System.currentTimeMillis();
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public CheckDeviceData getData() {
return data;
}
public void setData(CheckDeviceData data) {
this.data = data;
}
public long getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(long serialNumber) {
this.serialNumber = serialNumber;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CheckDevice that = (CheckDevice) o;
return serialNumber == that.serialNumber &&
Objects.equals(action, that.action) &&
Objects.equals(data, that.data);
}
@Override
public int hashCode() {
return Objects.hash(action, data, serialNumber);
}
@Override
public String toString() {
return "CheckDevice{" +
"action='" + action + '\'' +
", data=" + data +
", serialNumber=" + serialNumber +
'}';
}
private static class CheckDeviceData {
private String equipmentId;
private CheckDeviceData(String deviceSN) {
this.equipmentId = deviceSN;
}
public String getEquipmentId() {
return equipmentId;
}
public void setEquipmentId(String equipmentId) {
this.equipmentId = equipmentId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CheckDeviceData that = (CheckDeviceData) o;
return Objects.equals(equipmentId, that.equipmentId);
}
@Override
public int hashCode() {
return Objects.hash(equipmentId);
}
@Override
public String toString() {
return "CheckDeviceData{" +
"equipmentId='" + equipmentId + '\'' +
'}';
}
}
}
......@@ -3,13 +3,11 @@ package com.bgycc.smartcanteen.socket;
import android.annotation.SuppressLint;
import android.net.ConnectivityManager;
import android.net.Network;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.bgycc.smartcanteen.entity.CheckDevice;
import com.bgycc.smartcanteen.entity.Heartbeat;
import com.bgycc.smartcanteen.executor.SCTaskExecutor;
import com.bgycc.smartcanteen.state.ConnectState;
......@@ -45,8 +43,6 @@ public class SCWebSocketClient extends WebSocketClient {
private static final long SWITCH_INTERVAL = 10 * 1000;
private static final String RESPONSE_ACTION = "action";
private static final String RESPONSE_DATA = "data";
private static final String CHECK_DEVICE = "CHECK_DEVICE";
private static SCWebSocketClient instance;
private Gson gson;
......@@ -169,21 +165,6 @@ public class SCWebSocketClient extends WebSocketClient {
if (jsonObject.has(RESPONSE_ACTION)) {
action = jsonObject.get(RESPONSE_ACTION).getAsString();
}
// 是否服务器下发的心跳通知(响应则告知服务器设备未断开链接)
if (action.equals(CHECK_DEVICE)) {
String data = "";
if (jsonObject.has(RESPONSE_DATA)) {
data = jsonObject.get(RESPONSE_DATA).getAsString();
}
if (!TextUtils.isEmpty(data)) {
CheckDevice ack = new CheckDevice(CHECK_DEVICE, data);
String requestStr = gson.toJson(ack);
send(requestStr);
}
// 该指令不需要向外通知Listener
LogUtils.d(TAG, "后台下发心跳包: " + response);
return;
}
LogUtils.d(TAG, "收到后台消息: " + response);
for (SCWebSocketListener l : listener) {
l.onMessage(action, jsonObject, response);
......
package com.bgycc.smartcanteen.utils;
import android.os.Build;
import com.bgycc.smartcanteen.qrcode.IQRCodeScan;
import com.bgycc.smartcanteen.qrcode.QRCodeScanFactory;
import com.blankj.utilcode.util.PathUtils;
import java.io.File;
......@@ -12,6 +15,7 @@ import java.io.File;
public class DeviceProxy {
public static final String DEVICE_MODEL_TPS = "TPS";
public static final String DEVICE_MODEL_QUAD = "QUAD";
private static final String QUAD_SYSTEM_LOG = "boot_log";
public static IQRCodeScan createQRCodeScan() throws Exception {
return QRCodeScanFactory.create();
......@@ -20,4 +24,15 @@ public class DeviceProxy {
public static boolean updateApp(File updateApk) {
return InstallManager.install(updateApk);
}
public static String getSystemLogDir() {
String model = Build.MODEL;
if (model.contains(DEVICE_MODEL_TPS)) {
return PathUtils.getExternalStoragePath() + File.separator + QUAD_SYSTEM_LOG;
} else if (model.contains(DEVICE_MODEL_QUAD)) {
return PathUtils.getExternalStoragePath() + File.separator + QUAD_SYSTEM_LOG;
} else {
return PathUtils.getExternalStoragePath() + File.separator + QUAD_SYSTEM_LOG;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment