Commit f022264b by pye52

Merge branch 'master' into rel-1.3.6

parents 002c8477 4189ff05
package com.bgycc.smartcanteen.command; package com.bgycc.smartcanteen.command;
import androidx.work.BackoffPolicy;
import androidx.work.Data; import androidx.work.Data;
import androidx.work.ListenableWorker; import androidx.work.ListenableWorker;
import androidx.work.OneTimeWorkRequest; import androidx.work.OneTimeWorkRequest;
...@@ -9,6 +10,7 @@ import com.google.gson.Gson; ...@@ -9,6 +10,7 @@ import com.google.gson.Gson;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit;
public class CommandHelper { public class CommandHelper {
private static final String LOG_UPLOAD = "LOG_PULL"; private static final String LOG_UPLOAD = "LOG_PULL";
...@@ -72,6 +74,11 @@ public class CommandHelper { ...@@ -72,6 +74,11 @@ public class CommandHelper {
worker = new OneTimeWorkRequest.Builder(workerClass) worker = new OneTimeWorkRequest.Builder(workerClass)
.setInputData(inputData) .setInputData(inputData)
.addTag(command.getAction()) .addTag(command.getAction())
.setBackoffCriteria(
BackoffPolicy.LINEAR,
OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS
)
.build(); .build();
} }
return worker; return worker;
......
...@@ -8,6 +8,7 @@ import androidx.work.WorkerParameters; ...@@ -8,6 +8,7 @@ import androidx.work.WorkerParameters;
import com.bgycc.smartcanteen.api.SCApi; import com.bgycc.smartcanteen.api.SCApi;
import com.bgycc.smartcanteen.api.SCRetrofit; import com.bgycc.smartcanteen.api.SCRetrofit;
import com.bgycc.smartcanteen.entity.CommandLog; import com.bgycc.smartcanteen.entity.CommandLog;
import com.bgycc.smartcanteen.utils.DeviceProxy;
import com.blankj.utilcode.util.FileUtils; import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.LogUtils; import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.PathUtils; import com.blankj.utilcode.util.PathUtils;
...@@ -40,6 +41,8 @@ public class LogCommandWorker extends CommandWorker { ...@@ -40,6 +41,8 @@ public class LogCommandWorker extends CommandWorker {
private static final String ZIP_FILE = "log.zip"; private static final String ZIP_FILE = "log.zip";
private static final String UPLOAD_DIR = "upload_log"; private static final String UPLOAD_DIR = "upload_log";
private static final long DEFAULT_DELAY = 1000; 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 parseFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
private SimpleDateFormat nameFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); private SimpleDateFormat nameFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
...@@ -62,12 +65,21 @@ public class LogCommandWorker extends CommandWorker { ...@@ -62,12 +65,21 @@ public class LogCommandWorker extends CommandWorker {
return failed("日志上传指令不符合规范"); return failed("日志上传指令不符合规范");
} }
File logFile = getZipLogs(); File logFile = getZipLogs();
if (logFile != null) { if (logFile == null) {
inProgress("上传压缩文件至服务器"); return failed();
upload(logFile); }
inProgress("上传压缩文件至服务器");
if (upload(logFile)) {
return success(); 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() { private void parseDate() {
...@@ -106,8 +118,17 @@ public class LogCommandWorker extends CommandWorker { ...@@ -106,8 +118,17 @@ public class LogCommandWorker extends CommandWorker {
} }
if (uploadDir == null) return null; if (uploadDir == null) return null;
if (!copyTargetFiles(logDir, uploadDir)) { try {
LogUtils.d(TAG, "没有匹配的日志文件"); 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; return null;
} }
...@@ -132,7 +153,7 @@ public class LogCommandWorker extends CommandWorker { ...@@ -132,7 +153,7 @@ public class LogCommandWorker extends CommandWorker {
private File getLogDirByType(String logType) { private File getLogDirByType(String logType) {
File logDir; File logDir;
if (logType.equals(BOOT_LOG)) { if (logType.equals(BOOT_LOG)) {
logDir = new File(PathUtils.getExternalStoragePath(), "boot_log"); logDir = new File(DeviceProxy.getSystemLogDir());
} else { } else {
logDir = new File(LogUtils.getConfig().getDir()); logDir = new File(LogUtils.getConfig().getDir());
} }
...@@ -161,6 +182,9 @@ public class LogCommandWorker extends CommandWorker { ...@@ -161,6 +182,9 @@ public class LogCommandWorker extends CommandWorker {
return date.after(startTime) && date.before(endTime); return date.after(startTime) && date.before(endTime);
}; };
List<File> logFiles = FileUtils.listFilesInDirWithFilter(src, filter, false, null); List<File> logFiles = FileUtils.listFilesInDirWithFilter(src, filter, false, null);
if (logFiles.isEmpty()) {
return true;
}
boolean copyResult = true; boolean copyResult = true;
inProgress("筛选目标日志文件"); inProgress("筛选目标日志文件");
int count = 0; int count = 0;
...@@ -173,10 +197,10 @@ public class LogCommandWorker extends CommandWorker { ...@@ -173,10 +197,10 @@ public class LogCommandWorker extends CommandWorker {
if (tempCopyResult) count++; if (tempCopyResult) count++;
} }
LogUtils.d(TAG, "待上传日志文件总数: " + logFiles.size() + ", 复制成功文件总数: " + 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(); OkHttpClient client = SCRetrofit.createOkHttpClientBuilder().build();
SCApi api = SCRetrofit.createApi(client); SCApi api = SCRetrofit.createApi(client);
CommandLog.CommandLogData data = commandLog.getData(); CommandLog.CommandLogData data = commandLog.getData();
...@@ -190,9 +214,11 @@ public class LogCommandWorker extends CommandWorker { ...@@ -190,9 +214,11 @@ public class LogCommandWorker extends CommandWorker {
MultipartBody.Part body = MultipartBody.Part.createFormData("file", fileNameForServer, requestBody); MultipartBody.Part body = MultipartBody.Part.createFormData("file", fileNameForServer, requestBody);
try { try {
Response<String> response = api.upload(body).execute(); Response<String> response = api.upload(body).execute();
LogUtils.d(TAG, "日志文件上传成功: " + response); LogUtils.d(TAG, "日志文件上传完毕: " + response);
return response.isSuccessful();
} catch (IOException e) { } catch (IOException e) {
LogUtils.e(TAG, "日志文件上传失败: " + e.getMessage()); LogUtils.e(TAG, "日志文件上传失败: " + e.getMessage());
return false;
} finally { } finally {
FileUtils.delete(uploadDir); FileUtils.delete(uploadDir);
FileUtils.delete(zip); 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; ...@@ -3,13 +3,11 @@ package com.bgycc.smartcanteen.socket;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.Network; import android.net.Network;
import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import com.bgycc.smartcanteen.entity.CheckDevice;
import com.bgycc.smartcanteen.entity.Heartbeat; import com.bgycc.smartcanteen.entity.Heartbeat;
import com.bgycc.smartcanteen.executor.SCTaskExecutor; import com.bgycc.smartcanteen.executor.SCTaskExecutor;
import com.bgycc.smartcanteen.state.ConnectState; import com.bgycc.smartcanteen.state.ConnectState;
...@@ -45,8 +43,6 @@ public class SCWebSocketClient extends WebSocketClient { ...@@ -45,8 +43,6 @@ public class SCWebSocketClient extends WebSocketClient {
private static final long SWITCH_INTERVAL = 10 * 1000; private static final long SWITCH_INTERVAL = 10 * 1000;
private static final String RESPONSE_ACTION = "action"; 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 static SCWebSocketClient instance;
private Gson gson; private Gson gson;
...@@ -169,21 +165,6 @@ public class SCWebSocketClient extends WebSocketClient { ...@@ -169,21 +165,6 @@ public class SCWebSocketClient extends WebSocketClient {
if (jsonObject.has(RESPONSE_ACTION)) { if (jsonObject.has(RESPONSE_ACTION)) {
action = jsonObject.get(RESPONSE_ACTION).getAsString(); 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); LogUtils.d(TAG, "收到后台消息: " + response);
for (SCWebSocketListener l : listener) { for (SCWebSocketListener l : listener) {
l.onMessage(action, jsonObject, response); l.onMessage(action, jsonObject, response);
......
package com.bgycc.smartcanteen.utils; package com.bgycc.smartcanteen.utils;
import android.os.Build;
import com.bgycc.smartcanteen.qrcode.IQRCodeScan; import com.bgycc.smartcanteen.qrcode.IQRCodeScan;
import com.bgycc.smartcanteen.qrcode.QRCodeScanFactory; import com.bgycc.smartcanteen.qrcode.QRCodeScanFactory;
import com.blankj.utilcode.util.PathUtils;
import java.io.File; import java.io.File;
...@@ -12,6 +15,7 @@ import java.io.File; ...@@ -12,6 +15,7 @@ import java.io.File;
public class DeviceProxy { public class DeviceProxy {
public static final String DEVICE_MODEL_TPS = "TPS"; public static final String DEVICE_MODEL_TPS = "TPS";
public static final String DEVICE_MODEL_QUAD = "QUAD"; public static final String DEVICE_MODEL_QUAD = "QUAD";
private static final String QUAD_SYSTEM_LOG = "boot_log";
public static IQRCodeScan createQRCodeScan() throws Exception { public static IQRCodeScan createQRCodeScan() throws Exception {
return QRCodeScanFactory.create(); return QRCodeScanFactory.create();
...@@ -20,4 +24,15 @@ public class DeviceProxy { ...@@ -20,4 +24,15 @@ public class DeviceProxy {
public static boolean updateApp(File updateApk) { public static boolean updateApp(File updateApk) {
return InstallManager.install(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