commit 692caf43cecb03ab4e68c738ccbb119a6659a704 Author: htjcAdmin Date: Thu Feb 27 11:37:35 2025 +0800 /* 修改偶现bug: 步骤如下: 1. 点击开始测试按钮,数据上报正常; 2. 点击结束检测按钮,弹出保存数据对话框; 3. 点击取消按钮。 4. 再次从过程1开始测试,出现无法识别的ID; 原因: 经过分析日志发现,再次点击测试的时候串口上报的数据没有正确处理,问题出现在串口适配层。 当2、3、4三个动作中间没有任何停留世间操作非常快的时候,这个问题成为必现问题,即使第3个 步骤点击保存按钮,再迅速操作第4个步骤也会出现问题。由这个现象进行分析,确定是由于操作 太快,此时串口并没有正常的关闭,就开始了下一个测试流程。 修改: 该问题有好几种修改方法,经过各方面权衡,采用一种最稳妥对于当前流程逻辑影响最小的方法: 1. 在保存数据对话框点击取消以后弹出一个“正在取消”的模态框,时间为8秒。 2. 延长“正在保存”对话框的时间为8秒。 */ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cae0cc5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +*.iml +.gradle +/local.properties +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +.DS_Store +/build +/captures +.externalNativeBuild + +.idea +.idea/ +app/libs/ +serialportlib/libs/ +serialportlib/src/main/res/drawable/ + +!app-release.apk \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..affc214 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +## HANDSET-JE002-EX + +### 说明 +传感器通过串口上报响应的检测数据:温度、湿度、内压、外压 + diff --git a/app-release.apk b/app-release.apk new file mode 100644 index 0000000..3b56e82 Binary files /dev/null and b/app-release.apk differ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..0587fec --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,74 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 27 + defaultConfig { + applicationId "com.handset.serialportsensor" + minSdkVersion 19 + targetSdkVersion 27 + versionCode 1 + versionName "2.3" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + javaCompileOptions { annotationProcessorOptions { includeCompileClasspath = true } } + multiDexEnabled true + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + lintOptions { + checkReleaseBuilds false + abortOnError false + } + + applicationVariants.all { variant -> + variant.outputs.all { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.apk')) { + //版本名-版本号-发布时间.apk + def fileName = "检测仪_JE002_EX_V${versionName}_${releaseTime()}.apk" + outputFileName = fileName + } + } + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation rootProject.ext.deps.appcompatV7 + implementation rootProject.ext.deps.recyclerviewV7 + implementation rootProject.ext.deps.constraintLayout + implementation rootProject.ext.deps.rvAdapterHelper + implementation rootProject.ext.deps.rvDivider + implementation rootProject.ext.deps.stickyDecoration + implementation rootProject.ext.deps.utils + implementation rootProject.ext.deps.jodaTime + implementation rootProject.ext.deps.rxJava + implementation rootProject.ext.deps.rxAndroid + + implementation 'com.android.support.constraint:constraint-layout:1.1.0' + implementation 'com.android.support:support-v4:27.1.1' + implementation 'com.android.support:design:27.1.1' + implementation 'org.projectlombok:lombok:1.16.16' + annotationProcessor "org.projectlombok:lombok:1.16.16" + compileOnly 'org.glassfish:javax.annotation:10.0-b28' + implementation 'com.squareup.retrofit2:converter-gson:2.2.0' + + implementation project(':serialportlib') + implementation 'com.github.suntiago:dblib:v1.0-beta' + implementation 'com.android.support:multidex:1.0.3' + implementation 'cn.jingzhuan.lib:chart:0.10.17@aar' + implementation 'com.google.guava:guava:22.0-android' +} + +def static releaseTime() { + return new Date().format("yyyyMMdd", TimeZone.getTimeZone("GMT+8")) +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/release/app-release.apk b/app/release/app-release.apk new file mode 100644 index 0000000..3b56e82 Binary files /dev/null and b/app/release/app-release.apk differ diff --git a/app/release/output.json b/app/release/output.json new file mode 100644 index 0000000..9f0c959 --- /dev/null +++ b/app/release/output.json @@ -0,0 +1 @@ +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..3a8f506 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/handset/serialportsensor/App.java b/app/src/main/java/com/handset/serialportsensor/App.java new file mode 100644 index 0000000..a90e50b --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/App.java @@ -0,0 +1,44 @@ +package com.handset.serialportsensor; + +import android.support.multidex.MultiDexApplication; + +import com.blankj.utilcode.util.Utils; +import com.handset.serialportsensor.account.AccountManager; +import com.handset.serialportsensor.db.DBUpdateHelperMY; +import com.handset.serialportsensor.utils.CrashHandler; +import com.handset.serialportsensor.utils.PersistHelper; +import com.handset.serialportsensor.utils.Slog; + +import net.danlew.android.joda.JodaTimeAndroid; + +import org.kymjs.kjframe.KJDB; + +public class App extends MultiDexApplication { + static boolean debug = BuildConfig.DEBUG; + + @Override + public void onCreate() { + super.onCreate(); + + Utils.init(this); + + JodaTimeAndroid.init(this); + + Slog.init(this); + Slog.setDebug(true, true); + Slog.enableSaveLog(true); + + KJDB.create(this, "htjc_sensor_history.db", !debug, DBUpdateHelperMY.DATABASE_VERSION, new DBUpdateHelperMY()); + + /* + * 初始化账户组件,不使用自动登录 + * */ + AccountManager.init((this), debug); + + //保存Crash的Log + CrashHandler crashHandler = CrashHandler.getInstance(); + crashHandler.init(getApplicationContext()); + + PersistHelper.init((this)); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/BootReceiver.java b/app/src/main/java/com/handset/serialportsensor/BootReceiver.java new file mode 100644 index 0000000..aad1b29 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/BootReceiver.java @@ -0,0 +1,24 @@ +package com.handset.serialportsensor; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.handset.serialportsensor.activity.Main2Activity; +import com.handset.serialportsensor.utils.Slog; + + +public class BootReceiver extends BroadcastReceiver { + + private final String TAG = getClass().getSimpleName(); + + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { + Slog.d(TAG, "Receive Broadcast"); + Intent bootIntent = new Intent(context, Main2Activity.class); + bootIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(bootIntent); + } + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/account/Account.java b/app/src/main/java/com/handset/serialportsensor/account/Account.java new file mode 100644 index 0000000..3c1f228 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/account/Account.java @@ -0,0 +1,11 @@ +package com.handset.serialportsensor.account; + +/** + * Created by Jeremy on 2018/8/2. + */ + +public class Account { + //账户id + public String userId; + public String token; +} diff --git a/app/src/main/java/com/handset/serialportsensor/account/AccountManager.java b/app/src/main/java/com/handset/serialportsensor/account/AccountManager.java new file mode 100644 index 0000000..2fa9793 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/account/AccountManager.java @@ -0,0 +1,169 @@ +package com.handset.serialportsensor.account; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import com.handset.serialportsensor.utils.SPUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * Created by Jeremy on 2018/8/2. + * 账户管理应用,适用于单用户系统 + */ + +@SuppressWarnings(value = "unused") +public class AccountManager { + private final String TAG = getClass().getSimpleName(); + private static String AccountManager_user_id = "AccountManager_user_id"; + private static String AccountManager_account_token = "AccountManager_account_token"; + + private static AccountManager sAccountManager; + private Context sContext; + //账户ID + private Account mAccount; + private List mAccountStatusCallbacks = new ArrayList<>(); + private HashMap> mCallbackListHashMap = new HashMap<>(); + + public static AccountManager get() { + if (sAccountManager == null) { + throw new NullPointerException("please init AccountManager first before getting"); + } + return sAccountManager; + } + + private AccountManager(Context sContext, boolean autoLogin) { + this.sContext = sContext; + if (autoLogin) { + autoLogin(); + } + } + + public static void init(Context context) { + init(context, false); + } + + public static void init(Context context, boolean autoLogin) { + if (sAccountManager == null) { + sAccountManager = new AccountManager(context, autoLogin); + } + } + + public boolean isLogin() { + Log.i(TAG, "mAccount.userId: " + mAccount.userId); + return mAccount != null && !TextUtils.isEmpty(mAccount.userId); + } + + public String getUserData(String key) { + if (isLogin()) { + return SPUtils.getInstance(sContext).get(mAccount.userId + key); + } + return null; + } + + public void putUserData(String key, String data) { + Log.d(TAG, "putUserData [key, data]:" + key + " " + data); + if (isLogin()) { + SPUtils.getInstance(sContext).put(mAccount.userId + key, data); + if (mAccountStatusCallbacks.size() > 0) { + for (AccountStatusCallback accountStatusCallback : mAccountStatusCallbacks) { + if (mCallbackListHashMap.containsKey(accountStatusCallback)) { + for (String s : mCallbackListHashMap.get(accountStatusCallback)) { + if (key.equals(s)) { + accountStatusCallback.userInfoChange(key); + break; + } + } + } else { + accountStatusCallback.userInfoChange(key); + } + } + } + } + } + + public String getUserId() { + if (isLogin()) { + return mAccount.userId; + } + return ""; + } + + public String getToken() { + return isLogin() ? mAccount.token : ""; + } + + private void autoLogin() { + String account = "admin"/*SPUtils.getInstance(sContext).get(AccountManager_user_id)*/; + String token = SPUtils.getInstance(sContext).get(account + AccountManager_account_token); + setAccount(account, token); + } + + public void login(String userId, String token) { + setAccount(userId, token); + Log.i(TAG, "login [userId, pwd]:" + userId + " " + token + ""); + } + + public void logout() { + Log.i(TAG, "logout []:" + getUserId()); + setAccount("", ""); + } + + private void setAccount(String userId, String token) { + if (mAccount == null) { + mAccount = new Account(); + } + mAccount.userId = userId; + mAccount.token = token; + SPUtils.getInstance(sContext).put(AccountManager_user_id, userId); + SPUtils.getInstance(sContext).put(userId + AccountManager_account_token, token); + if (mAccountStatusCallbacks.size() > 0) { + if (isLogin()) { + for (AccountStatusCallback accountStatusCallback : mAccountStatusCallbacks) { + accountStatusCallback.loginCallback(); + } + } else { + for (AccountStatusCallback accountStatusCallback : mAccountStatusCallbacks) { + accountStatusCallback.logoutCallback(); + } + } + } + } + + /*初次注册,立即回调一下*/ + public void registerAccountStatusCallBack(AccountStatusCallback statusCallback) { + registerAccountStatusCallBack(statusCallback, null); + } + + + /*初次注册,立即回调一下*/ + + /** + * @param statusCallback 回调参数 + * @param interestKeys 感兴趣的字段,默认回调所有的字段 + */ + private void registerAccountStatusCallBack(AccountStatusCallback statusCallback, List interestKeys) { + if (!mAccountStatusCallbacks.contains(mAccountStatusCallbacks)) { + mAccountStatusCallbacks.add(statusCallback); + if (interestKeys != null && interestKeys.size() > 0) { + if (mCallbackListHashMap.containsKey(statusCallback)) { + mCallbackListHashMap.remove(statusCallback); + } + mCallbackListHashMap.put(statusCallback, interestKeys); + } + if (isLogin()) { + statusCallback.loginCallback(); + } else { + //statusCallback.logoutCallback(); + } + } + } + + public void unregisterAccountStatusCallBack(AccountStatusCallback statusCallback) { + mAccountStatusCallbacks.remove(statusCallback); + mCallbackListHashMap.remove(statusCallback); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/account/AccountStatusCallback.java b/app/src/main/java/com/handset/serialportsensor/account/AccountStatusCallback.java new file mode 100644 index 0000000..011bf6e --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/account/AccountStatusCallback.java @@ -0,0 +1,13 @@ +package com.handset.serialportsensor.account; + +/** + * Created by Jeremy on 2018/8/2. + */ + +public interface AccountStatusCallback { + void loginCallback(); + + void logoutCallback(); + + void userInfoChange(String key); +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/BaseActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/BaseActivity.java new file mode 100644 index 0000000..ff6aaad --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/BaseActivity.java @@ -0,0 +1,124 @@ +package com.handset.serialportsensor.activity; + +import android.app.AlertDialog; +import android.os.Handler; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; + +import com.handset.serialportlib.CRCUtils; + +public abstract class BaseActivity extends AppCompatActivity { + private static final String logTag = "HANDSET-JE002-EX"; + + private boolean mResume = false; + boolean mNeedToDismissProgressDlg = false; + boolean mNeedToShowProgressDlg = false; + AlertDialog mLoadingDialog; + + @Override + protected void onResume() { + super.onResume(); + this.mResume = true; + checkProgress(); + } + + @Override + protected void onPause() { + this.mResume = false; + super.onPause(); + } + + protected String genCmd(String sensorNo, int cmdId) { + try { + String content = sensorNo.concat("00" + Integer.toHexString(cmdId) + "00"); + return "DDDD" + content + CRCUtils.genCrc(content); + } catch (Exception e) { + Log.e(logTag, e.getMessage()); + return null; + } + } + + public void showDialog(final AlertDialog loadingDialog) { + if (loadingDialog == null) { + return; + } + mLoadingDialog = loadingDialog; + if (mResume) { + mLoadingDialog.show(); + mNeedToShowProgressDlg = false; + } else { + mNeedToShowProgressDlg = true; + } + } + + private void checkProgress() { + if (mLoadingDialog != null && mResume) { + if (mNeedToShowProgressDlg) { + mLoadingDialog.show(); + mNeedToShowProgressDlg = false; + } + if (mNeedToDismissProgressDlg) { + mLoadingDialog.dismiss(); + mNeedToDismissProgressDlg = false; + mLoadingDialog = null; + } + } + } + + public void dismissDialog(final AlertDialog loadingDialog) { + if (loadingDialog == null && mLoadingDialog == null) { + return; + } + if (mResume) { + if (loadingDialog != null && loadingDialog.isShowing()) { + loadingDialog.dismiss(); + } else if (mLoadingDialog != null && mLoadingDialog.isShowing()) { + mLoadingDialog.dismiss(); + } + + mNeedToDismissProgressDlg = false; + mLoadingDialog = null; + } else { + mLoadingDialog = loadingDialog; + mNeedToDismissProgressDlg = true; + } + } + + public void disMissDialogDelay(final AlertDialog alertDialog, int delayMillis) { + new Handler().postDelayed(() -> dismissDialogD(alertDialog), delayMillis); + } + + + protected void dismissDialogD(final AlertDialog alertDialog) { + if (mLoadingDialog == null && alertDialog == null) { + return; + } + + if (mLoadingDialog != null && alertDialog != null && mLoadingDialog == alertDialog) { + dismissDialog(alertDialog); + return; + } + + if (mLoadingDialog == null) { + if (mResume && alertDialog.isShowing()) { + alertDialog.dismiss(); + } + } + + } + + + public void disMissLoadingDialog(final AlertDialog loadingDialog) { + runOnUiThread(() -> { + /*if (loadingDialog != null && loadingDialog.isShowing()) { + loadingDialog.dismiss(); + }*/ + dismissDialog(loadingDialog); + }); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/BaudRateSettingActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/BaudRateSettingActivity.java new file mode 100644 index 0000000..36d00d0 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/BaudRateSettingActivity.java @@ -0,0 +1,265 @@ +package com.handset.serialportsensor.activity; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.util.Log; +import android.view.View; + +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.handset.serialportlib.ByteUtils; +import com.handset.serialportlib.CRCUtils; +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.bean.RawData; +import com.handset.serialportsensor.constant.Constant; +import com.handset.serialportsensor.presenter.SurfaceContract; +import com.handset.serialportsensor.presenter.SurfacePresenter; +import com.handset.serialportsensor.utils.ToastHelper; + +import java.util.Arrays; + +public class BaudRateSettingActivity extends BaseActivity implements View.OnClickListener, SurfaceContract.ISerialView { + private final String logTag = "HANDSET-JE002-EX"; + + private TextView tvBr9600; + private TextView tvBr19200; + private TextView tvNum3; + private ImageView ivBr9600; + private ImageView ivBr19200; + private ImageView ivBr38400; + + private byte baudByte = 0x01; + private Integer baudRate; + private String sensorId; + + private AlertDialog baudSettingsDialog; + + private SurfacePresenter mPresenter = new SurfacePresenter((this)); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_baudrate_setting); + Intent intent = getIntent(); + if (intent != null) { + baudRate = intent.getIntExtra(Constant.BAUD_RATE, (38400)); + sensorId = intent.getStringExtra(Constant.SENSOR_ID); + } + initView(); + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + protected void onDestroy() { + mPresenter.close(); + super.onDestroy(); + } + + private void initView() { + TextView tvTitle = findViewById(R.id.title_text); + ImageView ivBack = findViewById(R.id.title_back); + TextView tvConfirm = findViewById(R.id.tv_confirm); + RelativeLayout rlNum1 = findViewById(R.id.rl_br_9600); + RelativeLayout rlNum2 = findViewById(R.id.rl_br_19200); + RelativeLayout rlNum3 = findViewById(R.id.rl_br_38400); + tvBr9600 = findViewById(R.id.tv_br_9600); + tvBr19200 = findViewById(R.id.tv_br_19200); + tvNum3 = findViewById(R.id.tv_br_38400); + ivBr9600 = findViewById(R.id.iv_br_9600); + ivBr19200 = findViewById(R.id.iv_br_19200); + ivBr38400 = findViewById(R.id.iv_br_38400); + tvTitle.setText(R.string.baud_rate_setting); + ivBack.setVisibility(View.VISIBLE); + tvConfirm.setVisibility(View.VISIBLE); + tvConfirm.setText(R.string.confirm); + tvBr9600.setTextColor(getResources().getColor(R.color.colorPrimaryDark)); + ivBr9600.setVisibility(View.VISIBLE); + ivBack.setOnClickListener(this); + tvConfirm.setOnClickListener(this); + rlNum1.setOnClickListener(this); + rlNum2.setOnClickListener(this); + rlNum3.setOnClickListener(this); + if (baudRate == 38400) { + clickId(R.id.rl_br_38400); + } else if (baudRate == 19200) { + clickId(R.id.rl_br_19200); + } else if (baudRate == 9600) { + clickId(R.id.rl_br_9600); + } + } + + @Override + public void onClick(View view) { + clickId(view.getId()); + } + + private void clickId(int id) { + switch (id) { + case R.id.title_back: + this.finish(); + break; + case R.id.tv_confirm: + if (ivBr9600.getVisibility() == View.VISIBLE) { + baudByte = 0x01; + } else if (ivBr19200.getVisibility() == View.VISIBLE) { + baudByte = 0x02; + } else { + baudByte = 0x03; + } + setBaudRate(); + break; + case R.id.rl_br_9600: + tvBr9600.setTextColor(getResources().getColor(R.color.colorPrimaryDark)); + tvBr19200.setTextColor(getResources().getColor(R.color.text_general_color)); + tvNum3.setTextColor(getResources().getColor(R.color.text_general_color)); + ivBr9600.setVisibility(View.VISIBLE); + ivBr19200.setVisibility(View.GONE); + ivBr38400.setVisibility(View.GONE); + break; + case R.id.rl_br_19200: + tvBr9600.setTextColor(getResources().getColor(R.color.text_general_color)); + tvBr19200.setTextColor(getResources().getColor(R.color.colorPrimaryDark)); + tvNum3.setTextColor(getResources().getColor(R.color.text_general_color)); + ivBr9600.setVisibility(View.GONE); + ivBr19200.setVisibility(View.VISIBLE); + ivBr38400.setVisibility(View.GONE); + break; + case R.id.rl_br_38400: + tvBr9600.setTextColor(getResources().getColor(R.color.text_general_color)); + tvBr19200.setTextColor(getResources().getColor(R.color.text_general_color)); + tvNum3.setTextColor(getResources().getColor(R.color.colorPrimaryDark)); + ivBr9600.setVisibility(View.GONE); + ivBr19200.setVisibility(View.GONE); + ivBr38400.setVisibility(View.VISIBLE); + break; + default: + break; + } + } + + private void setBaudRate() { + Log.i(logTag, ("Setting BaudRate:" + baudRate)); + showSettingDialog(); + + new Thread( + () -> { + Looper.prepare(); + new Handler().postDelayed(() -> mPresenter.open(baudRate), (300)); + Looper.loop(); + } + ).start(); + + handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_3C, (3300)); + new Handler().postDelayed(() -> { + if (baudSettingsDialog != null && baudSettingsDialog.isShowing()) { + baudSettingsDialog.dismiss(); + setBaudFailed(); + } + }, (10000)); + } + + @SuppressLint("HandlerLeak") + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + if (msg.what == Constant.Command.COMMAND_3C) {//波特率设置 + Log.i(logTag, ("baud rate set: sensorId: " + sensorId)); + StringBuilder sb = new StringBuilder(sensorId); + sb.append("00").append("3C").append("01").append("0".concat(String.valueOf(baudByte))); + String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); + Log.i(logTag, "baud rate set: cooked: " + cooked); + Log.i(logTag, "baud rate set: cooked 2: " + Arrays.toString(cooked.getBytes())); + mPresenter.write(cooked); + } + } + }; + + //正在设置波特率 + private void showSettingDialog() { + runOnUiThread(() -> baudSettingsDialog = ToastHelper.showTipDialog((BaudRateSettingActivity.this), R.mipmap.ic_setting, R.string.set_baud_rate_now_tips)); + } + + @Override + public void onSerialOpen(boolean isOpen) { + + } + + @Override + public void onSerialBaudRate(Integer baudRate) { + + } + + @Override + public void onSerialData(RawData rawData) { + if (rawData.getItemType() == RawData.TYPE_RECEIVE) { + String message = rawData.getMessage(); + Log.i(logTag, ("BaudRateSettingActivity, onSerialData: " + message)); + byte[] bytes = ByteUtils.hexStrToBytes(message); + if ((bytes[6] & 0xff) == 0x0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_3D) { + mPresenter.close(); + if (baudSettingsDialog != null && baudSettingsDialog.isShowing()) { + baudSettingsDialog.dismiss(); + } + setBaudSuccess(); + } + } + } + + @Override + public void onSerialError(Integer errorCode) { + + } + + //波特率设置成功 + private void setBaudSuccess() { + runOnUiThread(() -> { + disMissLoadingDialog(baudSettingsDialog); + ToastHelper.showSubmitDialog( + getString(R.string.set_baud_rate_success), + R.mipmap.img_right, + getString(R.string.go_back_init_screen_content), + getResources().getColor(R.color.blue_button_bg), + getString(R.string.btn_ensure), BaudRateSettingActivity.this, + (View view) -> { + finish(); + Intent intent = new Intent((BaudRateSettingActivity.this), Main2Activity.class); + intent.putExtra(Constant.SENSOR_ID, sensorId); + startActivity(intent); + }); + }); + + } + + //波特率设置失败 + private void setBaudFailed() { + runOnUiThread(() -> { + disMissLoadingDialog(baudSettingsDialog); + ToastHelper.showSubmitDialog( + getString(R.string.set_baud_rate_failed), + R.mipmap.img_cross, + getString(R.string.go_back_init_screen_content), + getResources().getColor(R.color.button), + getString(R.string.btn_ensure), + (BaudRateSettingActivity.this), + (View view) -> finish() + ); + }); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/ChangeSensorIdSettingsActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/ChangeSensorIdSettingsActivity.java new file mode 100644 index 0000000..c437376 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/ChangeSensorIdSettingsActivity.java @@ -0,0 +1,192 @@ +package com.handset.serialportsensor.activity; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.handset.serialportlib.ByteUtils; +import com.handset.serialportlib.CRCUtils; +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.bean.RawData; +import com.handset.serialportsensor.constant.Constant; +import com.handset.serialportsensor.presenter.SurfaceContract; +import com.handset.serialportsensor.presenter.SurfacePresenter; +import com.handset.serialportsensor.utils.ToastHelper; + +import java.util.Arrays; + +/** + * Created by zy on 2019/2/23. + */ + +public class ChangeSensorIdSettingsActivity extends BaseActivity implements SurfaceContract.ISerialView { + private static final String logTag = "HANDSET-JE002-EX"; + + private String sensorId; + private Integer baudRate; + private EditText etSensorId; + private SurfacePresenter mPresenter = new SurfacePresenter((this)); + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_change_sensor_id_setings); + Intent intent = getIntent(); + if (intent != null) { + sensorId = intent.getStringExtra(Constant.SENSOR_ID); + baudRate = intent.getIntExtra(Constant.BAUD_RATE, (38400)); + } + etSensorId = findViewById(R.id.et_sensor_id); + findViewById(R.id.btn_save).setOnClickListener((View v) -> save()); + initTitle(); + etSensorId.setText(sensorIdToInt(sensorId)); + } + + @Override + protected void onDestroy() { + mPresenter.close(); + super.onDestroy(); + } + + private String sensorIdToInt(String sensorId) { + byte[] bytes = ByteUtils.hexStrToBytes(sensorId); + Log.i(logTag, "sensorId hexStrToBytes: " + Arrays.toString(bytes)); + int no = ((bytes[0] & 0xff) * 100 + (bytes[1] & 0xff)) * 10000 + ((bytes[2] & 0xff) << 8) + (bytes[3] & 0xff); + String s = "00000000".concat(String.valueOf(no)); + return s.substring(s.length() - 8); + } + + private void initTitle() { + ImageView ivBack = findViewById(R.id.title_back); + ivBack.setVisibility(View.VISIBLE); + ivBack.setOnClickListener((View view) -> finish()); + TextView tvTitle = findViewById(R.id.title_text); + tvTitle.setText(R.string.id_setting); + } + + private void save() { + String sensorId = etSensorId.getText().toString(); + if (TextUtils.isEmpty(sensorId) || sensorId.length() != 8) { + Toast.makeText((this), R.string.id_must_8bits_tip, Toast.LENGTH_SHORT).show(); + } else { + boolean tagAccept = true; + for (int i = 0; i < 8; i++) { + char a = sensorId.charAt(i); + if (!from0to9(a)) { + Toast.makeText((this), R.string.id_must_8bits_tip, Toast.LENGTH_SHORT).show(); + tagAccept = false; + break; + } + } + if (tagAccept) { + showSettingDialog(); + new Thread( + () -> { + Looper.prepare(); + new Handler().postDelayed(() -> mPresenter.open(baudRate), (500)); + Looper.loop(); + } + ).start(); + + handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_50, (3500)); + } + } + } + + private AlertDialog settingsDialog; + + private void showSettingDialog() { + runOnUiThread(() -> { + settingsDialog = ToastHelper.showTipDialog((ChangeSensorIdSettingsActivity.this), R.mipmap.ic_setting, R.string.id_setting_tip); + //disMissDialogDelay(settingsDialog, (10000)); + dismissSettingDialogDelay(); + } + ); + } + + private Handler dismissHandler = new Handler(); + private Runnable dismissRunnable; + private void dismissSettingDialogDelay() { + dismissRunnable = () -> { + dismissDialogD(settingsDialog); + runOnUiThread(() -> Toast.makeText((ChangeSensorIdSettingsActivity.this), R.string.sensor_id_set_fail, Toast.LENGTH_SHORT).show()); + }; + dismissHandler.postDelayed(dismissRunnable, (10000)); + } + + @SuppressLint("HandlerLeak") + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + if (msg.what == Constant.Command.COMMAND_50) {//设置传感器ID + StringBuilder sb = new StringBuilder(sensorId); + byte[] bytes = ByteUtils.getByte4Id(etSensorId.getText().toString()); + String hexString = ByteUtils.bytesToHexStr(bytes); + Log.i(logTag, "sensor no set: sensor prior: " + Arrays.toString(bytes)); + Log.i(logTag, "sensor no set: hexString: " + hexString); + + sb.append("00").append("50").append("04").append(hexString); + String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); + Log.i(logTag, "sensor no set: cooked: " + cooked); + Log.i(logTag, "sensor no set: cooked 2: " + Arrays.toString(cooked.getBytes())); + mPresenter.write(cooked); + } + } + }; + + private boolean from0to9(char c) { + return (c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9'); + } + + @Override + public void onSerialOpen(boolean isOpen) { + + } + + @Override + public void onSerialBaudRate(Integer baudRate) { + + } + + @Override + public void onSerialData(RawData rawData) { + if (rawData.getItemType() == RawData.TYPE_RECEIVE) { + Log.i(logTag, "ChangeSensorIdSettingsActivity, onSerialData: " + rawData.getMessage()); + byte[] bytes = ByteUtils.hexStrToBytes(rawData.getMessage()); + Log.i(logTag, "ChangeSensorIdSettingsActivity, onSerialData 2: " + Arrays.toString(bytes)); + if (bytes.length >= 8) { + if ((bytes[6] & 0xff) == 0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_51) { + Log.i(logTag, "ChangeSensorIdSettingsActivity, onSerialData, 0x51 feedback: " + rawData.getMessage()); + mPresenter.close(); + dismissDialog(settingsDialog); + dismissHandler.removeCallbacks(dismissRunnable); + runOnUiThread(() -> Toast.makeText((ChangeSensorIdSettingsActivity.this), R.string.sensor_id_set_success, Toast.LENGTH_SHORT).show()); + finish(); + Intent intent = new Intent((ChangeSensorIdSettingsActivity.this), Main2Activity.class); + intent.putExtra(Constant.SENSOR_ID, sensorId); + startActivity(intent); + } else { + runOnUiThread(() -> Toast.makeText((ChangeSensorIdSettingsActivity.this), R.string.sensor_id_set_fail, Toast.LENGTH_SHORT).show()); + } + } + } + } + + @Override + public void onSerialError(Integer errorCode) { + + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/ConeSettingActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/ConeSettingActivity.java new file mode 100644 index 0000000..9fe20eb --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/ConeSettingActivity.java @@ -0,0 +1,258 @@ +package com.handset.serialportsensor.activity; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.text.TextUtils; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.blankj.utilcode.util.ToastUtils; +import com.handset.serialportlib.ByteUtils; +import com.handset.serialportlib.CRCUtils; +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.bean.RawData; +import com.handset.serialportsensor.constant.Constant; +import com.handset.serialportsensor.presenter.SurfaceContract; +import com.handset.serialportsensor.presenter.SurfacePresenter; +import com.handset.serialportsensor.utils.ToastHelper; + +import java.util.Arrays; + +public class ConeSettingActivity extends BaseActivity implements SurfaceContract.ISerialView { + private static final String TAG = "HANDSET-JE002-EX"; + + private Integer baudRate; + private String sensorId; + boolean eggNoRes = false, coneNoRes = false, coneUsedTimesRes = false, eggTypeRes = false; + + private AlertDialog settingsDialog; + private AlertDialog getSettingsDialog; + + private SurfacePresenter mPresenter = new SurfacePresenter((this)); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_cone_setting); + Intent intent = getIntent(); + if (intent != null) { + baudRate = intent.getIntExtra(Constant.BAUD_RATE, (38400)); + sensorId = intent.getStringExtra(Constant.SENSOR_ID); + } + initView(); + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + protected void onDestroy() { + mPresenter.close(); + super.onDestroy(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if (im != null) { + View view = getCurrentFocus(); + if (view != null) { + im.hideSoftInputFromWindow(getCurrentFocus().getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + } + return super.onTouchEvent(event); + } + + private void initView() { + initTitle(); + } + + public void onClickBtnSave(View view) { + String value = ((EditText) (findViewById(R.id.et_egg_num))).getText().toString(); + String value2 = ((EditText) (findViewById(R.id.et_cone_num))).getText().toString(); + String value3 = ((EditText) (findViewById(R.id.et_use_num))).getText().toString(); + String value4 = ((EditText) (findViewById(R.id.et_egg_type))).getText().toString(); + + if(TextUtils.isEmpty(value) && TextUtils.isEmpty(value2) &&TextUtils.isEmpty(value3) && TextUtils.isEmpty(value4)) { + ToastUtils.showShort(getString(R.string.input_empty)); + } else { + showSettingDialog(); + new Thread( + () -> { + Looper.prepare(); + new Handler().postDelayed(() -> mPresenter.open(baudRate), (500)); + Looper.loop(); + } + ).start(); + handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_32, (3500)); + handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_36, (3700)); + handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_3A, (3800)); + handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_40, (3900)); + handler.sendEmptyMessageDelayed(Constant.READ_TIME_OUT, (10000)); + } + } + + private void initTitle() { + ImageView ivBack = findViewById(R.id.title_back); + ivBack.setVisibility(View.VISIBLE); + ivBack.setOnClickListener((View view) -> finish()); + TextView tvTitle = findViewById(R.id.title_text); + tvTitle.setText(R.string.cone_info_title); + } + + @SuppressLint("HandlerLeak") + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + if (msg.what == Constant.Command.COMMAND_32) {//弹号设置 + String value = ((EditText) (findViewById(R.id.et_egg_num))).getText().toString(); + if (!TextUtils.isEmpty(value)) { + Log.i(TAG, "egg no set: sensorId: " + sensorId); + StringBuilder sb = new StringBuilder(sensorId); + //String length = "0".concat(String.valueOf(value.length())); + String length = "0".concat(Integer.toHexString(value.length())); + String length2 = length.substring(length.length() - 2); + //Log.i(TAG, "egg no set: length2: " + length2); + sb.append("00").append("32").append(length2).append(ByteUtils.strToHexStr(value)); + String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); + Log.i(TAG, "egg no set: cooked: " + cooked); + Log.i(TAG, "egg no set: cooked 2: " + Arrays.toString(cooked.getBytes())); + mPresenter.write(cooked); + } + } else if (msg.what == Constant.Command.COMMAND_36) {//筒号设置 + String value = ((EditText) (findViewById(R.id.et_cone_num))).getText().toString(); + if (!TextUtils.isEmpty(value)) { + StringBuilder sb = new StringBuilder(sensorId); + //String length = "0".concat(String.valueOf(value.length())); + String length = "0".concat(Integer.toHexString(value.length())); + String length2 = length.substring(length.length() - 2); + sb.append("00").append("36").append(length2).append(ByteUtils.strToHexStr(value)); + + String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); + Log.i(TAG, "cone no set: cooked: " + cooked); + + mPresenter.write(cooked); + } + } else if (msg.what == Constant.Command.COMMAND_3A) {//弹筒使用次数设置 + String value = ((EditText) (findViewById(R.id.et_use_num))).getText().toString(); + if (!TextUtils.isEmpty(value)) { + StringBuilder sb = new StringBuilder(sensorId); + String length = "0".concat(String.valueOf(value.length())); + String length2 = length.substring(length.length() - 2); + sb.append("00").append("3A").append(length2).append(ByteUtils.strToHexStr(value)); + + String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); + Log.i(TAG, "cone used times set: cooked: " + cooked); + + mPresenter.write(cooked); + } + } else if (msg.what == Constant.Command.COMMAND_40) { // 弹型 + String value = ((EditText) (findViewById(R.id.et_egg_type))).getText().toString(); + if (!TextUtils.isEmpty(value)) { + StringBuilder sb = new StringBuilder(sensorId); + String length = "0".concat(Integer.toHexString(value.length())); + String length2 = length.substring(length.length() - 2); + sb.append("00").append("40").append(length2).append(ByteUtils.strToHexStr(value)); + String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); + Log.i(TAG, "egg type set: cooked: " + cooked); + + mPresenter.write(cooked); + } + } else if (msg.what == Constant.READ_TIME_OUT) { + if (eggNoRes || coneNoRes || coneUsedTimesRes || eggTypeRes) { + /*ToastUtils.showShort(R.string.setting_success);*/ + runOnUiThread(() -> { + disMissLoadingDialog(settingsDialog); + if (!(getSettingsDialog != null && getSettingsDialog.isShowing())) { + getSettingsDialog = ToastHelper.showSubmitDialog( + getString(R.string.set_cone_info_success), + R.mipmap.img_right, + getString(R.string.go_back_init_screen_content), + getResources().getColor(R.color.blue_button_bg), + getString(R.string.btn_ensure), + (ConeSettingActivity.this), + (View view) -> finish() + ); + } + }); + } else { + runOnUiThread(() -> { + disMissLoadingDialog(settingsDialog); + if (!(getSettingsDialog != null && getSettingsDialog.isShowing())) { + getSettingsDialog = ToastHelper.showSubmitDialog( + getString(R.string.set_cone_info_failed), + R.mipmap.img_cross, + getString(R.string.go_back_init_screen_content), + getResources().getColor(R.color.blue_button_bg), + getString(R.string.btn_ensure), + (ConeSettingActivity.this), + (View view) -> finish() + ); + } + }); + } + + /*findViewById(R.id.btn_save).setEnabled(true); + findViewById(R.id.btn_save).setBackgroundResource(R.drawable.bg_start_btn_new); + ((Button) findViewById(R.id.btn_save)).setText(R.string.save_settings);*/ + } + } + }; + + @Override + public void onSerialOpen(boolean isOpen) { + + } + + @Override + public void onSerialBaudRate(Integer baudRate) { + + } + + @Override + public void onSerialData(RawData rawData) { + if (rawData.getItemType() == RawData.TYPE_RECEIVE) { + String message = rawData.getMessage(); + Log.i(TAG, "ConeSettingActivity, onSerialData: " + message); + byte[] bytes = ByteUtils.hexStrToBytes(message); + + if ((bytes[6] & 0xff) == 0x0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_33) { //egg no + eggNoRes = ((bytes[9] & 0xff) == 0xff); + } else if ((bytes[6] & 0xff) == 0x0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_37) { //cone no + coneNoRes = (bytes[9] & 0xff) == 0xff; + } else if ((bytes[6] & 0xff) == 0x0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_3B) { //cone used times + coneUsedTimesRes = (bytes[9] & 0xff) == 0xff; + } else if ((bytes[6] & 0xff) == 0x0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_41) { //egg type + eggTypeRes = (bytes[9] & 0xff) == 0xff; + } + } + } + + @Override + public void onSerialError(Integer errorCode) { + + } + + private void showSettingDialog() { + runOnUiThread(() -> settingsDialog = ToastHelper.showTipDialog((ConeSettingActivity.this), R.mipmap.ic_setting, R.string.write_info_now_tips)); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/DataRecoverActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/DataRecoverActivity.java new file mode 100644 index 0000000..65d954d --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/DataRecoverActivity.java @@ -0,0 +1,238 @@ +package com.handset.serialportsensor.activity; + +import android.app.AlertDialog; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.constraint.ConstraintLayout; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + + +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.utils.DateUtils; +import com.handset.serialportsensor.utils.Slog; +import com.handset.serialportsensor.utils.ToastHelper; +import com.handset.serialportsensor.utils.ExcelMa; +import com.handset.serialportsensor.utils.PersistHelper; +import com.handset.serialportsensor.view.ExportProgressDialog; +import com.handset.serialportsensor.view.LinearLayoutManagerCus; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import static com.handset.serialportsensor.utils.DateStyle.YYYY_MM_DD_HH_MM_SS; + +/** + * Created by zy on 2019/3/11. + */ + +public class DataRecoverActivity extends BaseActivity { + private final String TAG = getClass().getSimpleName(); + private RecyclerView mRecyclerView; + private MyAdapter myAdapter; + + boolean isRecovering = false; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_recover_data); + TextView tvTitle = findViewById(R.id.title_text); + ImageView ivBack = findViewById(R.id.title_back); + tvTitle.setText(R.string.data_recovery); + ivBack.setVisibility(View.VISIBLE); + ivBack.setOnClickListener((View v) -> onBackPressed()); + findViewById(R.id.btn_sure).setOnClickListener((View v) -> { + int index = myAdapter.getSelectIndex(); + if (index != -1) { + showRecoverConfirm(index); + } + }); + mRecyclerView = findViewById(R.id.recycle_view); + mRecyclerView.setLayoutManager(new LinearLayoutManagerCus((this))); + DefaultItemAnimator animator = new DefaultItemAnimator(); + animator.setRemoveDuration(1000); + mRecyclerView.setItemAnimator(animator); + getLocalFiles(); + } + + ExcelMa excelMa = new ExcelMa(); + + boolean recoverStatus = true; + + private void recoverExcel(final int index) { + if (mFiles != null) { + mExportProgressDialog = null; + new Thread(() -> + excelMa.onReadClick(mFiles.get(index), new PersistHelper.ExportCallback() { + @Override + public void exportProgress(int counts, int remain) { + updateView(counts, remain); + recoverStatus = true; + } + + @Override + public void finish(int counts, int remain) { + if (remain != 0) { + showCancelTip(); + recoverStatus = true; + } else { + recoverStatus = false; + } + } + }) + ).start(); + } + } + + private void showCancelTip() { + runOnUiThread(() -> { + AlertDialog alertDialog = ToastHelper.showTipDialogNoShow((DataRecoverActivity.this), R.mipmap.chuchang_gray, R.string.cancel); + showDialog(alertDialog); + disMissDialogDelay(alertDialog, (3000)); + }); + } + + private void showRecoverConfirm(final int index) { + runOnUiThread(() -> { + dismissDialog((null)); + showExportProgress((0), (0)); + AlertDialog a = ToastHelper.showChooseDialogNoShow(getString(R.string.data_recovery_confirm), R.mipmap.ic_exclamation_mark, + getString(R.string.recover_data_alarm), getResources().getColor(R.color.button), + getString(R.string.confirm), getString(R.string.cancel), (DataRecoverActivity.this), new ToastHelper.OnDialogClickListener() { + @Override + public void onOKClickListener(View view) { + recoverExcel(index); + } + + @Override + public void onCancelClickListener(View view) { + + } + }); + showDialog(a); + }); + } + + public void updateView(int counts, int remain) { + showExportProgress(counts, remain); + } + + ExportProgressDialog mExportProgressDialog; + + private void showExportProgress(final int count, final int remain) { + if (mExportProgressDialog == null) { + runOnUiThread(() -> { + mExportProgressDialog = new ExportProgressDialog(); + mExportProgressDialog.showExportDialogNoShow((DataRecoverActivity.this), + (View view) -> { + if (recoverStatus) { + excelMa.stopExport(); + } else { + DataRecoverActivity.this.finish(); + } + }, count, remain, getString(R.string.data_recovering), getString(R.string.recovery_data)); + showDialog(mExportProgressDialog.mAlertDialog); + }); + } else { + mExportProgressDialog.update((this), count, remain); + } + } + + @Override + public void onBackPressed() { + if (!isRecovering) { + DataRecoverActivity.this.finish(); + } + } + + List mFiles; + + private void getLocalFiles() { + mFiles = Slog.getFiles(ExcelMa.getSavePath(), new ArrayList<>()); + initData(mFiles); + } + + void initData(List list) { + //设置适配器 + myAdapter = new MyAdapter(list); + myAdapter.setOnItemClickListener((View view, int position) -> { + }); + mRecyclerView.setAdapter(myAdapter); + } + + static class ViewHolder extends RecyclerView.ViewHolder { + TextView tvName; + TextView tv_file_size; + TextView tv_end_time; + ImageView ivSelect; + ConstraintLayout cl_content; + + ViewHolder(@NonNull View itemView) { + super(itemView); + tvName = itemView.findViewById(R.id.tv_name); + tv_file_size = itemView.findViewById(R.id.tv_file_size); + tv_end_time = itemView.findViewById(R.id.tv_end_time); + ivSelect = itemView.findViewById(R.id.iv_select); + cl_content = itemView.findViewById(R.id.cl_content); + } + } + + static class MyAdapter extends RecyclerView.Adapter { + List mDataList; + private OnItemClickListener mOnItemClickListener; + int indexSelect = -1; + + MyAdapter(List mList) { + this.mDataList = mList; + } + + int getSelectIndex() { + return indexSelect; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + return new ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.revocer_data_item, null, false)); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder viewHolder, final int i) { + File f = mDataList.get(viewHolder.getAdapterPosition()); + String text = f.length() / (1024) + "kb"; + viewHolder.tv_file_size.setText(text); + viewHolder.tvName.setText(f.getName()); + viewHolder.tv_end_time.setText(DateUtils.formatMilliesTimestamp(f.lastModified(), YYYY_MM_DD_HH_MM_SS)); + if (indexSelect == viewHolder.getAdapterPosition()) { + viewHolder.ivSelect.setImageResource(R.mipmap.ic_selected); + } else { + viewHolder.ivSelect.setImageResource(R.mipmap.ic_default); + } + viewHolder.cl_content.setOnClickListener((View v) -> { + indexSelect = viewHolder.getAdapterPosition(); + notifyDataSetChanged(); + }); + } + + @Override + public int getItemCount() { + return mDataList.size(); + } + + void setOnItemClickListener(OnItemClickListener onItemClickListener) { + this.mOnItemClickListener = onItemClickListener; + } + } + + public interface OnItemClickListener { + void onItemClick(View view, int position); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/HistoryActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/HistoryActivity.java new file mode 100644 index 0000000..bea7432 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/HistoryActivity.java @@ -0,0 +1,284 @@ +package com.handset.serialportsensor.activity; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.bean.Sensor; +import com.handset.serialportsensor.bean.TestRecordsTotal; +import com.handset.serialportsensor.constant.Constant; +import com.handset.serialportsensor.utils.Utils; +import com.handset.serialportsensor.view.LinearLayoutManagerCus; + +import org.kymjs.kjframe.KJDB; + +import java.util.List; + +public class HistoryActivity extends AppCompatActivity { + private static final String logTag = "HANDSET-JE002-EX"; + private boolean delStatus = false; + private RecyclerView mRecyclerView; + private MyAdapter myAdapter; + private LinearLayout llDeleteContent; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_history); + mRecyclerView = findViewById(R.id.recycle_view); + mRecyclerView.setLayoutManager(new LinearLayoutManagerCus(this)); + DefaultItemAnimator animator = new DefaultItemAnimator(); + animator.setRemoveDuration(1000); + mRecyclerView.setItemAnimator(animator); + initData(); + TextView tvTitle = findViewById(R.id.title_text); + ImageView ivBack = findViewById(R.id.title_back); + tvTitle.setText(R.string.test_history); + ivBack.setVisibility(View.VISIBLE); + ivBack.setOnClickListener((View v) -> HistoryActivity.this.finish()); + + Button btnSelAll = findViewById(R.id.btn_select_all); + btnSelAll.setOnClickListener((View v) -> myAdapter.selAll()); + Button btnDelete = findViewById(R.id.btn_delete); + btnDelete.setOnClickListener((View v) -> { + delStatus = false; + llDeleteContent.setVisibility(View.GONE); + myAdapter.delSelected(); + }); + Button btnCancel = findViewById(R.id.btn_cancel); + btnCancel.setOnClickListener((View v) -> { + llDeleteContent.setVisibility(View.GONE); + myAdapter.setDeleteStatus(false); + delStatus = false; + myAdapter.cancelSelected(); + }); + + llDeleteContent = findViewById(R.id.ll_delete_content); + llDeleteContent.setVisibility(View.GONE); + //initSensor(); + } + + void initData() { + final List sensors = KJDB.getDefaultInstance().findAll(Sensor.class); + for (Sensor sensor : sensors) { + Log.i(logTag, ("list every sensorId: " + sensor.sensor_id + ", id: " + sensor.id)); + } + if (myAdapter == null) { + myAdapter = new MyAdapter(sensors, (View v) -> { + if (delStatus) { + return true; + } else { + delStatus = true; + myAdapter.setDeleteStatus(true); + llDeleteContent.setVisibility(View.VISIBLE); + } + return false; + + }); + } + myAdapter.setOnItemClickListener((View view, int position) -> { + Intent intent = new Intent((HistoryActivity.this), HistoryDetailActivity.class); + Log.e(logTag, "History Activity id: " + sensors.get(position).id + ", sensorId: " + sensors.get(position).sensor_id); + intent.putExtra(Constant.SENSOR_ID, sensors.get(position).id); + startActivity(intent); + + }); + mRecyclerView.setAdapter(myAdapter); + } + + static class ViewHolder extends RecyclerView.ViewHolder { + private TextView tvEggNum; + private TextView tvEggType; + private TextView tvConeNo; + private TextView tvSensorId; + private TextView tvConeUsedTimes; + private TextView tvPro; + private LinearLayout llItem; + private ImageView ivSelectStatus; + + private ViewHolder(@NonNull View itemView) { + super(itemView); + tvEggNum = itemView.findViewById(R.id.tv_his_egg_num); + tvEggType = itemView.findViewById(R.id.tv_his_egg_type); + tvConeNo = itemView.findViewById(R.id.tv_his_cone_no); + tvSensorId = itemView.findViewById(R.id.tv_his_sensor_id); + tvPro = itemView.findViewById(R.id.tv_his_pro); + tvConeUsedTimes = itemView.findViewById(R.id.tv_his_cone_used_times); + llItem = itemView.findViewById(R.id.ll_his_item); + ivSelectStatus = itemView.findViewById(R.id.iv_select_status); + } + } + + public static class MyAdapter extends RecyclerView.Adapter { + private boolean delStatus = false; + private List mDataList; + private OnItemClickListener mOnItemClickListener; + private View.OnLongClickListener mOnLongClickListener; + + MyAdapter(List mList, View.OnLongClickListener longClickListener) { + this.mDataList = mList; + this.mOnLongClickListener = longClickListener; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + return new ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.history_item, viewGroup, (false))); + } + + @Override + public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int i) { + final Sensor sensor = mDataList.get(i); + viewHolder.tvEggNum.setText(TextUtils.isEmpty(sensor.egg_id) ? " " : " ".concat(sensor.egg_id)); + viewHolder.tvEggType.setText(TextUtils.isEmpty(sensor.egg_type) ? " " : " ".concat(sensor.egg_type)); + viewHolder.tvConeNo.setText(TextUtils.isEmpty(sensor.tupe_id) ? " " : " ".concat(sensor.tupe_id)); + viewHolder.tvSensorId.setText(Utils.getSensorNoShow(String.valueOf(sensor.sensor_id))); + viewHolder.tvPro.setText(String.valueOf(sensor.sensor_id).length() < 5 ? "" : String.valueOf(String.valueOf(sensor.sensor_id).charAt(4))); + viewHolder.llItem.setOnLongClickListener((View v) -> { + if (mOnLongClickListener != null) { + mOnLongClickListener.onLongClick(v); + } + return false; + + }); + viewHolder.ivSelectStatus.setVisibility(this.delStatus ? View.VISIBLE : View.GONE); + if (delStatus) { + viewHolder.ivSelectStatus.setImageResource(sensor.tagBackup == 1 ? R.mipmap.ic_selected : R.mipmap.ic_default); + viewHolder.llItem.setOnClickListener((View v) -> { + sensor.tagBackup = sensor.tagBackup == 0 ? 1 : 0; + notifyDataSetChanged(); + }); + } else { + viewHolder.llItem.setOnClickListener((View v) -> { + if (mOnItemClickListener != null) { + mOnItemClickListener.onItemClick(v, viewHolder.getAdapterPosition()); + } + }); + } + viewHolder.tvConeUsedTimes.setText(" ".concat(TextUtils.isEmpty(sensor.tv_tupe_use_times) ? "0" : sensor.tv_tupe_use_times)); + } + + @Override + public int getItemCount() { + return mDataList.size(); + } + + private void setOnItemClickListener(OnItemClickListener onItemClickListener) { + this.mOnItemClickListener = onItemClickListener; + } + + private void setDeleteStatus(boolean delStatus) { + this.delStatus = delStatus; + notifyDataSetChanged(); + } + + void selAll() { + for (Sensor sensor : mDataList) { + sensor.tagBackup = 1; + } + notifyDataSetChanged(); + } + + private void delSelected() { + for (int i = mDataList.size() - 1; i >= 0; i--) { + Sensor t = mDataList.get(i); + if (t.tagBackup == 1) { + KJDB.getDefaultInstance().deleteByWhere(TestRecordsTotal.class, "sensor_id = " + t.sensor_id); + KJDB.getDefaultInstance().deleteById(Sensor.class, t.id); + mDataList.remove(i); + } + } + delStatus = false; + notifyDataSetChanged(); + } + + private void cancelSelected() { + for (Sensor sensor : mDataList) { + sensor.tagBackup = 0; + } + } + } + + public interface OnItemClickListener { + void onItemClick(View view, int position); + } + + @SuppressWarnings(value = "all") + void initSensor() { + Sensor sensor = new Sensor(); + sensor.id = 1; + sensor.egg_id = "EGG1"; + sensor.sensor_id = 19011111; + sensor.egg_type = "EGGA"; + sensor.tupe_id = "TUPEA"; + KJDB.getDefaultInstance().save(sensor); + sensor.id = 2; + sensor.egg_id = "EGG2"; + sensor.sensor_id = 19011112; + sensor.egg_type = "EGGB"; + sensor.tupe_id = "TUPEB"; + KJDB.getDefaultInstance().save(sensor); + + TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); + int i = 1; + for (; i < 25; i++) { + + testRecordsTotal.id = i; + testRecordsTotal.end_time = System.currentTimeMillis(); + testRecordsTotal.Hum = 80; + testRecordsTotal.sensor_id = 1; + testRecordsTotal.pressure_yacha = 100; + testRecordsTotal.pressurein = 90; + testRecordsTotal.pressureout = 120; + testRecordsTotal.temp = 50; + testRecordsTotal.Hum20 = 90; + testRecordsTotal.pressurein20 = 20; + testRecordsTotal.tupe_use_times = "10"; + KJDB.getDefaultInstance().save(testRecordsTotal); + } + i = 1; + for (; i < 25; i++) { + testRecordsTotal.id = i; + testRecordsTotal.Hum = 80; + testRecordsTotal.sensor_id = 1; + testRecordsTotal.pressure_yacha = 100; + testRecordsTotal.pressurein = 90; + testRecordsTotal.pressureout = 120; + testRecordsTotal.temp = 50; + testRecordsTotal.Hum20 = 90; + testRecordsTotal.pressurein20 = 20; + testRecordsTotal.tupe_use_times = "10"; + KJDB.getDefaultInstance().save(testRecordsTotal); + } + + i = 1; + for (; i < 25; i++) { + testRecordsTotal.id = i; + testRecordsTotal.end_time = System.currentTimeMillis() - 2 * 24 * 60 * 60 * 1000; + testRecordsTotal.Hum = 80; + testRecordsTotal.sensor_id = 1; + testRecordsTotal.pressure_yacha = 100; + testRecordsTotal.pressurein = 90; + testRecordsTotal.pressureout = 120; + testRecordsTotal.temp = 50; + testRecordsTotal.Hum20 = 90; + testRecordsTotal.pressurein20 = 20; + testRecordsTotal.tupe_use_times = "10"; + KJDB.getDefaultInstance().save(testRecordsTotal); + } + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/HistoryDetailActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/HistoryDetailActivity.java new file mode 100644 index 0000000..1135538 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/HistoryDetailActivity.java @@ -0,0 +1,482 @@ +package com.handset.serialportsensor.activity; + +import android.app.DatePickerDialog; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.Button; +import android.widget.DatePicker; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.gson.Gson; +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.bean.Sensor; +import com.handset.serialportsensor.bean.TestRecordsTotal; +import com.handset.serialportsensor.bean.ThresholdBean; +import com.handset.serialportsensor.constant.Constant; +import com.handset.serialportsensor.utils.DateUtils; +import com.handset.serialportsensor.utils.SPUtils; +import com.handset.serialportsensor.utils.SpUtil; +import com.handset.serialportsensor.utils.Utils; +import com.handset.serialportsensor.view.AutoLoadMoreListView; + +import org.kymjs.kjframe.KJDB; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import static com.handset.serialportsensor.utils.DateStyle.YYYY_MM_DD; +import static com.handset.serialportsensor.utils.DateStyle.YYYY_MM_DD_HH_MM_SS; + +/** + * Created by zy on 2019/2/24. + */ +public class HistoryDetailActivity extends AppCompatActivity { + private static final String logTag = "HANDSET-JE002-EX"; + + private final static int ZERO = 0; + private final static boolean FALSE = false; + private final static boolean TRUE = true; + private final static int REQUEST_START_TIME = 100; + private final static int REQUEST_END_TIME = 101; + private final static int PAGE_SIZE = 8; //每页显示的数据条数 + + private boolean delStatus = false; + private TextView tvStartTime; + private TextView tvEndTime; + + private Sensor mSensor; + private LinearLayout llDeleteContent; + private AutoLoadMoreListView mRecyclerView; + private MyAdapter myAdapter; + private int currentPagedIndex = 0;//当前页码 + + private TextView etCurPage; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_history_detail); + int id = getIntent().getIntExtra(Constant.SENSOR_ID, ZERO); + mSensor = KJDB.getDefaultInstance().findById(id, Sensor.class); + if (mSensor == null) { + finish(); + } + initView(); + initData(); + } + + void initView() { + tvStartTime = findViewById(R.id.tv_his_detail_start_time); + tvStartTime.setOnClickListener((View v) -> pickData(REQUEST_START_TIME)); + tvStartTime.setEnabled(true); + tvEndTime = findViewById(R.id.tv_his_detail_end_time); + tvEndTime.setOnClickListener((View v) -> pickData(REQUEST_END_TIME)); + etCurPage = findViewById(R.id.et_curr_page); + TextView tvTitle = findViewById(R.id.title_text); + ImageView ivBack = findViewById(R.id.title_back); + tvTitle.setText(Utils.getSensorNoShow(String.valueOf(mSensor.sensor_id))); + ivBack.setVisibility(View.VISIBLE); + ivBack.setOnClickListener((View v) -> HistoryDetailActivity.this.finish()); + + mRecyclerView = findViewById(R.id.recycle_view); + mRecyclerView.setShowLoadMore(true); + mRecyclerView.setLoadMoreListener((AutoLoadMoreListView listView) -> { + Log.d(logTag, "onLoadMoreBegin [listView]:"); + if (!loadAll) { + search((true)); + } + }); + Button btnSelAll = findViewById(R.id.btn_select_all); + btnSelAll.setOnClickListener((View v) -> myAdapter.selAll()); + Button btnDelete = findViewById(R.id.btn_delete); + btnDelete.setOnClickListener((View v) -> { + delStatus = false; + llDeleteContent.setVisibility(View.GONE); + myAdapter.delSelected(); + }); + Button btnCancel = findViewById(R.id.btn_cancel); + btnCancel.setOnClickListener((View v) -> { + llDeleteContent.setVisibility(View.GONE); + myAdapter.setDeleteStatus(false); + delStatus = false; + }); + llDeleteContent = findViewById(R.id.ll_delete_content); + llDeleteContent.setVisibility(View.GONE); + } + + void initData() { + Calendar calendar = Calendar.getInstance(); + calendar.set(calendar.get(Calendar.YEAR), + calendar.get(Calendar.MONTH), + calendar.get(Calendar.DAY_OF_MONTH), ZERO, ZERO, ZERO); + long t = calendar.getTimeInMillis(); + start_time = t - 31536000000L; + start_time = SPUtils.getInstance(this).get("search_history_start_time", start_time); + calendar.set(calendar.get(Calendar.YEAR), + calendar.get(Calendar.MONTH), + calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59); + end_time = calendar.getTimeInMillis(); + Log.i(logTag, ("initData, start_time: " + start_time + ", end_time: " + end_time)); + end_time = SPUtils.getInstance(this).get("search_history_end_time", end_time); + loadAll = false; + search((false)); + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + private TextView tvPreIn20; + private TextView tvHumidity20; + private TextView tvTemperature; + private TextView tvHumidity; + private TextView tvPreIn; + private TextView tvPreOut; + private TextView tvProId; + private TextView tvBotLv; + LinearLayout llTemperature; + LinearLayout llHumidity; + LinearLayout llPreIn; + LinearLayout llPreOut; + TextView tvPressureDiff; + + TextView tvStartTime; + TextView tvEndTime; + TextView tvItemIndex; + + LinearLayout llItem; + ImageView ivSelectStatus; + + private ViewHolder(@NonNull View itemView) { + super(itemView); + tvPreIn20 = itemView.findViewById(R.id.tv_in_pre_20); + tvHumidity20 = itemView.findViewById(R.id.tv_shidu20); + tvTemperature = itemView.findViewById(R.id.tv_temp); + tvHumidity = itemView.findViewById(R.id.tv_shidu); + tvPreIn = itemView.findViewById(R.id.tv_pre_in); + tvPreOut = itemView.findViewById(R.id.tv_pre_out); + llTemperature = itemView.findViewById(R.id.ll_temp); + llHumidity = itemView.findViewById(R.id.ll_shidu); + llPreIn = itemView.findViewById(R.id.ll_pre_in); + llPreOut = itemView.findViewById(R.id.ll_pre_out); + tvPressureDiff = itemView.findViewById(R.id.tv_yacha); + tvStartTime = itemView.findViewById(R.id.tv_start_time); + tvEndTime = itemView.findViewById(R.id.tv_end_time); + tvItemIndex = itemView.findViewById(R.id.tv_item_index); + tvProId = itemView.findViewById(R.id.tv_pro_id); + tvBotLv = itemView.findViewById(R.id.tv_botelv); + llItem = itemView.findViewById(R.id.ll_item); + ivSelectStatus = itemView.findViewById(R.id.iv_select_status); + } + } + + public static class MyAdapter extends BaseAdapter { + private Context mContext; + private ThresholdBean bean; + private boolean delStatus = false; + private List mDataList; + private View.OnLongClickListener mOnLongClickListener; + + private void setDataList(List mList) { + if (mDataList == null) { + mDataList = new ArrayList<>(); + } + mDataList.clear(); + mDataList.addAll(mList); + notifyDataSetChanged(); + } + + private void delSelected() { + for (int i = mDataList.size() - 1; i >= 0; i--) { + TestRecordsTotal t = mDataList.get(i); + if (t.tagBackup == 1) { + KJDB.getDefaultInstance().deleteById(TestRecordsTotal.class, t.id); + mDataList.remove(i); + } + } + this.delStatus = false; + notifyDataSetChanged(); + } + + private void selAll() { + for (TestRecordsTotal testRecordsTotal : mDataList) { + testRecordsTotal.tagBackup = 1; + } + notifyDataSetChanged(); + } + + private void setDeleteStatus(boolean status) { + this.delStatus = status; + notifyDataSetChanged(); + } + + private void appendDataList(List mList) { + if (mDataList == null) { + mDataList = new ArrayList<>(); + } + mDataList.addAll(mList); + notifyDataSetChanged(); + } + + private MyAdapter(Context context, List mList, View.OnLongClickListener longClickListener) { + this.mDataList = new ArrayList<>(); + mDataList.addAll(mList); + mContext = context; + + bean = new ThresholdBean(); + bean.setTemperatureFloor("-40"); + bean.setTemperatureCeiling("65"); + bean.setHumidityFloor("0"); + bean.setHumidityCeiling("100"); + bean.setInnerPressureFloor("80"); + bean.setInnerPressureCeiling("150"); + bean.setOuterPressureFloor("80"); + bean.setOuterPressureCeiling("150"); + bean.setDiffPressureFloor("-20"); + bean.setDiffPressureCeiling("30"); + String bean2 = (String) SpUtil.get(context, Constant.THRESHOLD_KEY, ""); + if (!TextUtils.isEmpty(bean2)) { + bean = new Gson().fromJson(bean2, ThresholdBean.class); + } + this.mOnLongClickListener = longClickListener; + } + + private void onBindViewHolder(@NonNull ViewHolder viewHolder, final int i) { + final TestRecordsTotal sensor = mDataList.get(i); + DecimalFormat df = new DecimalFormat("0.00"); + viewHolder.tvHumidity20.setText(df.format(sensor.Hum20)); + viewHolder.tvPreIn20.setText(df.format(sensor.pressurein20)); + viewHolder.tvTemperature.setText(df.format(sensor.temp)); + viewHolder.tvHumidity.setText(df.format(sensor.Hum)); + viewHolder.tvPreIn.setText(df.format(sensor.pressurein)); + viewHolder.tvPreOut.setText(df.format(sensor.pressureout)); + viewHolder.tvPressureDiff.setText(df.format(sensor.pressure_yacha)); + + String ids = String.valueOf(sensor.sensor_id); + viewHolder.tvProId.setText(ids.length() < 5 ? "" : ids.substring(4, 5)); + viewHolder.tvBotLv.setText(sensor.botelv); + viewHolder.tvStartTime.setVisibility(View.GONE); + viewHolder.tvEndTime.setText(DateUtils.formatMilliesTimestamp(sensor.end_time, YYYY_MM_DD_HH_MM_SS)); + if (bean != null) { + viewHolder.tvTemperature.setTextColor(Color.parseColor(sensor.temp > Float.parseFloat(bean.getTemperatureFloor()) && sensor.temp < Float.parseFloat(bean.getTemperatureCeiling()) ? "#333333" : "#F02323")); + viewHolder.tvHumidity.setTextColor(Color.parseColor(sensor.Hum > Float.parseFloat(bean.getHumidityFloor()) && sensor.Hum < Float.parseFloat(bean.getHumidityCeiling()) ? "#333333" : "#F02323")); + viewHolder.tvPreIn.setTextColor(Color.parseColor(sensor.pressurein > Float.parseFloat(bean.getInnerPressureFloor()) && sensor.pressurein < Float.parseFloat(bean.getInnerPressureCeiling()) ? "#333333" : "#F02323")); + viewHolder.tvPreOut.setTextColor(Color.parseColor(sensor.pressureout > Float.parseFloat(bean.getOuterPressureFloor()) && sensor.pressureout < Float.parseFloat(bean.getOuterPressureCeiling()) ? "#333333" : "#F02323")); + viewHolder.tvPressureDiff.setTextColor(Color.parseColor(sensor.pressure_yacha > Float.parseFloat(bean.getDiffPressureFloor()) && sensor.pressure_yacha < Float.parseFloat(bean.getDiffPressureCeiling()) ? "#333333" : "#F02323")); + } + viewHolder.llItem.setOnLongClickListener((View v) -> { + if (mOnLongClickListener != null) { + mOnLongClickListener.onLongClick(v); + } + return false; + }); + + viewHolder.ivSelectStatus.setVisibility(this.delStatus ? View.VISIBLE : View.GONE); + if (this.delStatus) { + viewHolder.ivSelectStatus.setImageResource(sensor.tagBackup == 1 ? R.mipmap.ic_selected : R.mipmap.ic_default); + viewHolder.llItem.setOnClickListener((View v) -> { + sensor.tagBackup = sensor.tagBackup == 0 ? 1 : 0; + notifyDataSetChanged(); + }); + } else { + viewHolder.llItem.setOnClickListener(null); + } + } + + private int getItemCount() { + return mDataList == null ? 0 : mDataList.size(); + } + + @Override + public int getCount() { + return getItemCount(); + } + + @Override + public Object getItem(int position) { + return mDataList.get(position); + } + + @Override + public long getItemId(int position) { + return 0; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + if (convertView == null) { + convertView = LayoutInflater.from(mContext).inflate(R.layout.activity_history_detail_item, parent, false); + viewHolder = new ViewHolder(convertView); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + onBindViewHolder(viewHolder, position); + return convertView; + } + + } + + private void pickData(final int requestCode) { + Calendar calendar2 = Calendar.getInstance(); + Log.e(logTag, ("startTime: " + start_time + ", end_time: " + end_time)); + calendar2.setTimeInMillis(requestCode == REQUEST_START_TIME ? start_time : end_time); + + new DatePickerDialog(this, (DatePicker view, int year, int month, int dayOfMonth) -> { + Calendar calendar = Calendar.getInstance(); + long t = calendar.getTimeInMillis(); + if (requestCode == REQUEST_END_TIME) { + calendar.set(year, month, dayOfMonth, 23, 59, 59); + if (t == 0) { + Toast.makeText(HistoryDetailActivity.this, "请选择结束时间", Toast.LENGTH_SHORT).show(); + } else { + t = calendar.getTimeInMillis(); + end_time = t; + SPUtils.getInstance(HistoryDetailActivity.this).put("search_history_end_time", end_time); + } + loadAll = false; + + search(false); + } else if (requestCode == REQUEST_START_TIME) { + calendar.set(year, month, dayOfMonth, 0, 0, 0); + if (t == 0) { + Toast.makeText(HistoryDetailActivity.this, "请选择开始时间", Toast.LENGTH_SHORT).show(); + } else { + t = calendar.getTimeInMillis(); + start_time = t; + SPUtils.getInstance(HistoryDetailActivity.this).put("search_history_start_time", start_time); + } + + loadAll = false; + search(false); + } + }, calendar2.get(Calendar.YEAR), calendar2.get(Calendar.MONTH), calendar2.get(Calendar.DAY_OF_MONTH)).show(); + } + + long start_time = 0; + long end_time = 0; + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + Log.d(logTag, ("result ok")); + } + } + + public long findStartId(long start_time, long end_time) {//查找perPageItems条 + if (start_time > end_time) return 0; + + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(end_time); + long startDatT = calendar.get(Calendar.DAY_OF_YEAR) + calendar.get(Calendar.YEAR) * 1000; + List t = KJDB.getDefaultInstance().findAllByWhere(TestRecordsTotal.class, "day_t = " + startDatT + " And sensor_id = " + mSensor.sensor_id, "end_time desc"); + long curId; + if (t != null && t.size() > 0) { + curId = t.get(0).id; + for (int i = 1; i < t.size(); i++) { + long tempId = t.get(i).id; + if (curId < tempId) { + curId = tempId; + } + } + + return curId; + } + return findStartId(start_time, end_time - 24 * 3600000); + } + + public TestRecordsTotal findNextItem(long start_time, long end_time) { + if (startId <= 0) { + return null; + } + TestRecordsTotal t = KJDB.getDefaultInstance().findById(startId, TestRecordsTotal.class); + startId--; + if (t != null) { + if (t.end_time >= start_time && t.end_time <= end_time) { + if (t.sensor_id != mSensor.sensor_id) { + return findNextItem(start_time, end_time); + } + return t; + } + } else { + return findNextItem(start_time, end_time); + } + return null; + } + + long startId = 0; + boolean loadAll = false; + + private void search(boolean append) { + if (!append) { + startId = 0; + } + if (start_time >= end_time) { + return; + } + tvStartTime.setText(DateUtils.formatMilliesTimestamp(start_time, YYYY_MM_DD)); + tvEndTime.setText(DateUtils.formatMilliesTimestamp(end_time, YYYY_MM_DD)); + if (startId == 0) { + startId = findStartId(start_time, end_time); + } + List testRecordsTotals = new ArrayList<>(); + boolean tagLoadMore = true; + if (startId != 0) { + for (int i = 0; i < PAGE_SIZE; i++) { + TestRecordsTotal t = findNextItem(start_time, end_time); + if (t != null) { + testRecordsTotals.add(t); + } + } + } + + if (testRecordsTotals.size() < PAGE_SIZE) { + tagLoadMore = false; + } + String curPageIndex = String.valueOf(currentPagedIndex + 1); + etCurPage.setText(curPageIndex); + mRecyclerView.setShowLoadMore(tagLoadMore); + updateListView(testRecordsTotals, append); + mRecyclerView.loadMoreComplete(); + } + + void updateListView(List list, boolean append) { + if (myAdapter == null) { + myAdapter = new MyAdapter((this), list, (View v) -> { + if (delStatus) { + return true; + } + + delStatus = true; + myAdapter.setDeleteStatus(true); + llDeleteContent.setVisibility(View.VISIBLE); + return false; + + }); + mRecyclerView.setAdapter(myAdapter); + } else { + if (append) { + myAdapter.appendDataList(list); + } else { + myAdapter.setDataList(list); + } + } + } +} + diff --git a/app/src/main/java/com/handset/serialportsensor/activity/LoginActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/LoginActivity.java new file mode 100644 index 0000000..9a9029e --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/LoginActivity.java @@ -0,0 +1,253 @@ +package com.handset.serialportsensor.activity; + +import android.app.AlertDialog; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.text.TextUtils; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.Toast; + +import com.blankj.utilcode.util.ToastUtils; +import com.handset.serialportlib.ByteUtils; +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.account.AccountManager; +import com.handset.serialportsensor.bean.RawData; +import com.handset.serialportsensor.constant.Constant; +import com.handset.serialportsensor.presenter.SurfaceContract; +import com.handset.serialportsensor.presenter.SurfacePresenter; +import com.handset.serialportsensor.utils.ToastHelper; +import com.handset.serialportsensor.utils.SPUtils; + +public class LoginActivity extends BaseActivity implements SurfaceContract.ISerialView/*implements ServiceConnection, SerialService.OnReadValueCallback, SerialService.OnMateBaudRateCallback*/ { + private static final String logTag = "HANDSET-JE002-EX"; + private static int role = Constant.SENIOR_ROLE; + private static final int DIALOG_TIMEOUT = 30000; + private static final int READ_TIMEOUT = 3000; + + private Boolean isReady = false; + private Integer baudRate; + private EditText etUserName; + private EditText etPwd; + + private AlertDialog alertDialog; + + private SurfacePresenter mPresenter; + + private Handler mHandlerIdRead = new Handler(); + Handler mHandlerAlertDialog = new Handler(); + private Runnable mRunnableIdRead, mRunnableAlertDialog; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + ImageView ivBack = findViewById(R.id.title_back); + findViewById(R.id.title_layout).setBackground(null); + ivBack.setVisibility(View.VISIBLE); + ivBack.setImageResource(R.mipmap.img_back); + ivBack.setOnClickListener((View view) -> finish()); + + etPwd = findViewById(R.id.et_pwd); + etUserName = findViewById(R.id.et_user_name); + + findViewById(R.id.btn_login).setOnClickListener((View view) -> login()); + mPresenter = new SurfacePresenter(this); + checkLoginStatus(); + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onStop() { + super.onStop(); + //mHandlerAlertDialog.removeCallbacks(mRunnableAlertDialog); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + //mHandlerAlertDialog.removeCallbacks(mRunnableAlertDialog); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + InputMethodManager im = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + if(im != null) { + View view = getCurrentFocus(); + if(view != null) { + im.hideSoftInputFromWindow(getCurrentFocus().getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + } + return super.onTouchEvent(event); + } + + private void login() { + if (checkoutLoginInfo()) { + Log.i(logTag, ("auth ok, go to setting view.")); + alertDialog = ToastHelper.showTipDialog((this), R.mipmap.img_loading, R.string.identifying); + new Thread( + () -> { + Looper.prepare(); + new Handler().postDelayed(() -> mPresenter.open(), (1000)); + Looper.loop(); + } + ).start(); + + mRunnableAlertDialog = () -> { + Log.i(logTag, ("alertDialog force close!")); + alertDialog.dismiss(); + }; + mHandlerAlertDialog.postDelayed(mRunnableAlertDialog, DIALOG_TIMEOUT); + } + } + + @Override + public void onSerialOpen(boolean isOpen) { + runOnUiThread(() -> { + if (isOpen) { + mRunnableIdRead = () -> { + String cmd = genCmd(("FFFFFFFF"), Constant.Command.COMMAND_25); + Log.e(logTag, "login activity cmd: " + cmd); + mPresenter.write(cmd); + new Thread( + () -> { + Looper.prepare(); + new Handler().postDelayed(() -> { + Log.i(logTag, ("login fetching sensor no ready: " + isReady)); + if (!isReady) { + Log.e(logTag, ("login watch dog check, no data report!")); + runOnUiThread(() -> { + ToastUtils.showShort(R.string.test_id_error); + if(alertDialog.isShowing()) { + alertDialog.dismiss(); + } + mHandlerAlertDialog.removeCallbacks(mRunnableAlertDialog); + LoginActivity.this.finish(); + new Thread( + () -> { + Looper.prepare(); + new Handler().post(() -> { + mPresenter.close(); + }); + Looper.loop(); + } + ).start(); + }); + } else { + Log.i(logTag, ("login watch dog check, data report normally")); + } + }, (1000)); + Looper.loop(); + } + ).start(); + //mPresenter.write("DDDDFFFFFFFF0025003E90"); + }; + mHandlerIdRead.postDelayed(mRunnableIdRead, READ_TIMEOUT); + } else { + Log.i(logTag, "port is closing!"); + } + }); + } + + @Override + public void onSerialBaudRate(Integer baudRate) { + this.baudRate = baudRate; + } + + @Override + public void onSerialData(RawData rawData) { + if (rawData.getItemType() == RawData.TYPE_RECEIVE) { + String data = rawData.getMessage(); + Log.i(logTag, ("LoginActivity onSerialData: " + data)); + if (data.length() == 22) { + isReady = true; + alertDialog.dismiss(); + mHandlerAlertDialog.removeCallbacks(mRunnableAlertDialog); + mPresenter.close(); + boolean isRoot = AccountManager.get().getUserId().equals("root"); + boolean sensorThirdEnable = SPUtils.getInstance(this).get(("sensor_third_enable"), (false)); + boolean isOwn = isOwnSensor(data); + Log.i(logTag, ("onSerialData: isRoot: " + isRoot + ", sensorThirdEnable: " + sensorThirdEnable + ", isOwn: " + isOwn)); + int roleType = (isRoot || sensorThirdEnable || isOwn) ? Constant.SENIOR_ROLE : Constant.NOT_CONNECTED_ROLE; + SensorSettingsActivity.open(this.baudRate, roleType, data.substring(4, 12), (LoginActivity.this)); + LoginActivity.this.finish(); + } + } + } + + private boolean isOwnSensor(String data) { + byte[] bytes = ByteUtils.hexStrToBytes(data.substring(0, data.length() - 4)); + int no = ((bytes[2] & 0xff) * 100 + (bytes[3] & 0xff)) * 10000 + ((bytes[4] & 0xff) << 8) + (bytes[5] & 0xff); + String s = "00000000".concat(String.valueOf(no)); + String sensorNo = s.substring(s.length() - 8); + Log.i(logTag, ("isThirdSensor: " + sensorNo + ", position[4]: " + sensorNo.charAt(4))); + + return sensorNo.charAt(4) == '1'; + } + + @Override + public void onSerialError(Integer errorCode) { + runOnUiThread(() -> { + ToastUtils.showShort(R.string.test_btl_error); + mPresenter.close(); + alertDialog.dismiss(); + LoginActivity.this.finish(); + }); + } + + + private void checkLoginStatus() { + if (AccountManager.get().isLogin()) { + login(); + } + } + + private boolean checkoutLoginInfo() { + if (AccountManager.get().isLogin()) { + return true; + } + String pwd = etPwd.getText().toString(); + String username = etUserName.getText().toString(); + if (TextUtils.isEmpty(username)) { + Toast.makeText((this), "登录失败,用户名为空", Toast.LENGTH_SHORT).show(); + return false; + } + if (TextUtils.isEmpty(pwd)) { + Toast.makeText((this), "登录失败,密码为空", Toast.LENGTH_SHORT).show(); + return false; + } + + String pwdSp = SPUtils.getInstance(this).get(username); + Log.i(logTag, "pwdSp: " + pwdSp + ", username: " + username); + if (TextUtils.isEmpty(pwdSp)) { + if ("root".equals(username) && "root".equals(pwd)) { + Toast.makeText((this), "root 登录成功", Toast.LENGTH_SHORT).show(); + AccountManager.get().login("root", "root"); + return true; + } + if ("admin".equals(username) && "admin".equals(pwd)) { + AccountManager.get().login("admin", "admin"); + Toast.makeText((this), "admin 登录成功", Toast.LENGTH_SHORT).show(); + return true; + } + } else { + if (pwdSp.equals(pwd)) { + AccountManager.get().login(username, pwdSp); + Toast.makeText((this), username + " 登录成功", Toast.LENGTH_SHORT).show(); + return true; + } + } + Toast.makeText((this), "登录失败,用户名或密码错误", Toast.LENGTH_SHORT).show(); + return false; + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/Main2Activity.java b/app/src/main/java/com/handset/serialportsensor/activity/Main2Activity.java new file mode 100644 index 0000000..d55db46 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/Main2Activity.java @@ -0,0 +1,624 @@ +package com.handset.serialportsensor.activity; + +import android.Manifest; +import android.app.AlertDialog; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.support.v4.app.ActivityCompat; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import com.blankj.utilcode.util.ToastUtils; +import com.google.common.base.Splitter; +import com.google.gson.Gson; +import com.handset.serialportlib.ByteUtils; +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.bean.RawData; +import com.handset.serialportsensor.bean.MetaData; +import com.handset.serialportsensor.bean.ThresholdBean; +import com.handset.serialportsensor.constant.Constant; +import com.handset.serialportsensor.presenter.SurfaceContract; +import com.handset.serialportsensor.presenter.SurfacePresenter; +import com.handset.serialportsensor.utils.Slog; +import com.handset.serialportsensor.utils.SpUtil; +import com.handset.serialportsensor.utils.ToastHelper; +import com.handset.serialportsensor.utils.PersistHelper; +import com.handset.serialportsensor.utils.StatusBarUtils; +import com.handset.serialportsensor.utils.Utils; +import com.handset.serialportsensor.widget.DashBoard; + +import java.text.DecimalFormat; + +public class Main2Activity extends BaseActivity implements SurfaceContract.ISerialView { + private static final String logTag = "HANDSET-JE002-EX"; + + private Integer baudRate = 38400; + private final static String FLOAT_TYPE = "0.00"; + private final static int STARTING_TIMEOUT = 3000; + private final static int SAVING_TIMEOUT = 7000; + private final static int WATCHDOG_TIMEOUT = 1000; + private static boolean readBtnStatusOpen = false; + private final static String DEFAULT_VALUE = "- - -"; + + private static ThresholdBean thresholdBean; + private SurfacePresenter mPresenter; + private static MetaData metaData = MetaData.builder().build(); + private DashBoard mDashBoardTemperature; + private DashBoard mDashBoardHumidity; + private DashBoard mDashBoardInnerPressure; + private DashBoard mDashBoardOuterPressure; + private DashBoard mDashBoardDiffPressure; + + private static String[] PERMISSIONS_STORAGE = { + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + }; + + private Handler mHandlerResetReadBtn = new Handler(); + private Runnable mRunnableResetReadBtn; + + private Handler mHandlerSaveClose = new Handler(); + private Runnable mRunnableSaveClose; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + StatusBarUtils.setTranslucentStatus(this); + StatusBarUtils.setStatusColor((this), (false), (true), R.color.white); + setContentView(R.layout.activity_main2); + initView(); + disableSettingBtn(); + thresholdBean = new Gson().fromJson((String) SpUtil.get((this), Constant.THRESHOLD_KEY, ("")), ThresholdBean.class); + if (thresholdBean == null) { + Log.i(logTag, ("onCreate: thresholdBean null")); + thresholdBean = ThresholdBean.builder() + .temperatureFloor("-40").temperatureCeiling("65") + .humidityFloor("0").humidityCeiling("100") + .innerPressureFloor("80").innerPressureCeiling("150") + .outerPressureFloor("80").outerPressureCeiling("150") + .diffPressureFloor("-20").diffPressureCeiling("30") + .build(); + } + SpUtil.put((this), Constant.THRESHOLD_KEY, new Gson().toJson(thresholdBean)); + Slog.i(logTag, ("onCreate, thresholdBean value: " + thresholdBean)); + //Slog.save(logTag, ("onCreate, thresholdBean value: " + thresholdBean)); + + mPresenter = new SurfacePresenter((this)); + mPresenter.initBLNStatus('0'); + + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + if (ActivityCompat.checkSelfPermission((this), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions((this), PERMISSIONS_STORAGE, (1)); + } + } + + // emulator + //initEmulator(); + } + + @Override + protected void onPause() { + super.onPause(); + Log.i(logTag, ("onPause, close bln")); + } + + @Override + protected void onResume() { + super.onResume(); + Slog.i(logTag, ("onResume, open bln")); + + thresholdBean = new Gson().fromJson((String) SpUtil.get((this), Constant.THRESHOLD_KEY, ("")), ThresholdBean.class); + if (thresholdBean == null) { + Log.i(logTag, ("onResume: thresholdBean null")); + } + if (thresholdBean != null) { + if (mDashBoardTemperature != null && mDashBoardTemperature.textStart != null) { + mDashBoardTemperature.textStart = thresholdBean.temperatureFloor; + } + + if (mDashBoardTemperature != null && mDashBoardTemperature.textEnd != null) { + mDashBoardTemperature.textEnd = thresholdBean.temperatureCeiling; + } + + // + if (mDashBoardHumidity != null && mDashBoardHumidity.textStart != null) { + mDashBoardHumidity.textStart = thresholdBean.humidityFloor; + } + + if (mDashBoardHumidity != null && mDashBoardHumidity.textEnd != null) { + mDashBoardHumidity.textEnd = thresholdBean.humidityCeiling; + } + + // + if (mDashBoardInnerPressure != null && mDashBoardInnerPressure.textStart != null) { + mDashBoardInnerPressure.textStart = thresholdBean.innerPressureFloor; + } + if (mDashBoardInnerPressure != null && mDashBoardInnerPressure.textEnd != null) { + mDashBoardInnerPressure.textEnd = thresholdBean.innerPressureCeiling; + } + + // + if (mDashBoardOuterPressure != null && mDashBoardOuterPressure.textStart != null) { + mDashBoardOuterPressure.textStart = thresholdBean.outerPressureFloor; + } + if (mDashBoardOuterPressure != null && mDashBoardOuterPressure.textEnd != null) { + mDashBoardOuterPressure.textEnd = thresholdBean.outerPressureCeiling; + } + + // + if (mDashBoardDiffPressure != null && mDashBoardDiffPressure.textStart != null) { + mDashBoardDiffPressure.textStart = thresholdBean.diffPressureFloor; + } + if (mDashBoardDiffPressure != null && mDashBoardDiffPressure.textEnd != null) { + mDashBoardDiffPressure.textEnd = thresholdBean.diffPressureCeiling; + } + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + Log.i(logTag, ("main activity destroy")); + mHandlerResetReadBtn.removeCallbacks(mRunnableResetReadBtn); + mPresenter.close(); + mPresenter.onDestroy(); + } + + private void initView() { + mDashBoardTemperature = findViewById(R.id.dashboard_temperature); + mDashBoardHumidity = findViewById(R.id.dashboard_humidity); + mDashBoardInnerPressure = findViewById(R.id.dashboard_inner_pressure); + mDashBoardOuterPressure = findViewById(R.id.dashboard_outer_pressure); + mDashBoardDiffPressure = findViewById(R.id.dashboard_diff_pressure); + } + + @SuppressWarnings(value = "unused") + private void initEmulator() { + mDashBoardTemperature.setSecondText("26.97"); + mDashBoardHumidity.setSecondText("31.61"); + mDashBoardInnerPressure.setSecondText("102.55"); + mDashBoardDiffPressure.setSecondText("-0.76"); + mDashBoardOuterPressure.setSecondText("103.32"); + } + + private void disableSettingBtn() { + ImageView ivSettings = findViewById(R.id.title_back); + ivSettings.setImageResource(R.mipmap.settings_disable); + ivSettings.setEnabled(false); + } + + private void enableSettingBtn() { + ImageView ivSettings = findViewById(R.id.title_back); + ivSettings.setImageResource(R.mipmap.settings); + ivSettings.setEnabled(true); + } + + private void disableHistoryBtn() { + ImageView ivSettings = findViewById(R.id.iv_start); + ivSettings.setImageResource(R.mipmap.history_disable); + ivSettings.setEnabled(false); + } + + private void enableHistoryBtn() { + ImageView ivSettings = findViewById(R.id.iv_start); + ivSettings.setImageResource(R.mipmap.history); + ivSettings.setEnabled(true); + } + + public void onClickBtnRead(View view) { + clearDashBoard(); + if (!readBtnStatusOpen) { + disableSettingBtn(); + disableHistoryBtn(); + readBtnToStartingState(); + new Thread( + () -> { + Looper.prepare(); + new Handler().post(() -> mPresenter.open()); + Looper.loop(); + } + ).start(); + } else { + mPresenter.close(); + resetStatus(); + showStopTestDialog(); + } + } + + private void showStopTestDialog() { + ToastHelper.showSaveSensorDialog((this), new ToastHelper.OnDialogClickListener() { + @Override + public void onOKClickListener(View view) { + PersistHelper.endTest(); + showSavingDataDialog(); + } + + @Override + public void onCancelClickListener(View view) { + PersistHelper.endTest((false)); + showCancelingDataDialog(); + } + }); + } + + private void showSavingDataDialog() { + runOnUiThread(() -> { + AlertDialog alertDialog = ToastHelper.showTipDialog((Main2Activity.this), R.mipmap.img_loading, R.string.saving); + mRunnableSaveClose = alertDialog::dismiss; + mHandlerSaveClose.postDelayed(mRunnableSaveClose, SAVING_TIMEOUT); + }); + } + + private void showCancelingDataDialog() { + runOnUiThread(() -> { + AlertDialog alertDialog = ToastHelper.showTipDialog((Main2Activity.this), R.mipmap.img_loading, R.string.canceling); + mRunnableSaveClose = alertDialog::dismiss; + mHandlerSaveClose.postDelayed(mRunnableSaveClose, SAVING_TIMEOUT); + }); + } + + public void onClickSettingBtn(View view) { + startActivity(new Intent((Main2Activity.this), LoginActivity.class)); + } + + public void onClickHistoryBtn(View view) { + startActivity(new Intent((Main2Activity.this), HistoryActivity.class)); + } + + @Override + public void onSerialOpen(boolean isOpen) { + runOnUiThread(() -> { + readBtnStatusOpen = isOpen; + if (isOpen) { + mRunnableResetReadBtn = () -> { + mPresenter.write(genCmd(("FFFFFFFF"), Constant.Command.COMMAND_25)); + new Thread( + () -> { + Looper.prepare(); + new Handler().postDelayed(() -> { + Log.i(logTag, ("metaData sensorNo: " + metaData.getSensorNo())); + if (TextUtils.isEmpty(metaData.getSensorNo())) { + Log.e(logTag, ("watch dog check, no data report!")); + runOnUiThread(() -> { + ToastUtils.showShort(R.string.test_id_error); + new Thread( + () -> { + Looper.prepare(); + new Handler().post(() -> { + mPresenter.close(); + }); + Looper.loop(); + } + ).start(); + }); + } else { + Log.i(logTag, ("watch dog check, data report normally")); + runOnUiThread(this::readBtnToStopState); + } + }, WATCHDOG_TIMEOUT); + Looper.loop(); + } + ).start(); + }; + mHandlerResetReadBtn.postDelayed(mRunnableResetReadBtn, STARTING_TIMEOUT); + } else { + Log.i(logTag, ("Testing closing")); + metaData.resetData(); + readBtnToState((false)); + //enableSettingBtn(); + enableHistoryBtn(); + } + }); + } + + @Override + public void onSerialBaudRate(Integer baudRate) { + this.baudRate = baudRate; + } + + @Override + public void onSerialData(RawData rawData) { + String message = rawData.getMessage(); + boolean res = rawData.getItemType() == RawData.TYPE_SEND + ? doSendMessage(message) + : doReceiveMessage(message); + Log.v(logTag, ("res: " + res)); + } + + @Override + public void onSerialError(Integer errorCode) { + runOnUiThread(() -> { + ToastUtils.showShort(R.string.test_btl_error); + readBtnToOriginState(); + //enableSettingBtn(); + enableHistoryBtn(); + }); + } + + private void setMakerNoView(int text) { + ((TextView) (findViewById(R.id.tv_maker))).setText(String.valueOf(text)); + } + + private void setSensorNoView(String text) { + //String textCooked = text.substring(0, 4) + text.substring(5); + ((TextView) (findViewById(R.id.tv_sensor_no))).setText(text); + } + + private void setEggNoView(String text) { + ((TextView) (findViewById(R.id.tv_egg_no))).setText(text); + } + + private void setEggTypeView(String text) { + ((TextView) (findViewById(R.id.tv_egg_type))).setText(text); + } + + private void setConeNoView(String text) { + ((TextView) (findViewById(R.id.tv_cone_no))).setText(text); + } + + private void setConeUsedTimesView(String text) { + ((TextView) (findViewById(R.id.tv_cone_used_times))).setText(text); + } + + private boolean doReceiveMessage(String contain) { + try { + Log.i(logTag, ("doReceiveMessage: " + contain)); + if (contain.length() < 100) { + doCalcBasicData(contain); + } else { + metaData.resetData20Degree(); + for (String data : Splitter.fixedLength(30).split(contain)) { + metaData.doCalcMeta(data); + } + metaData.doCalcMetaEx(); + + boolean valid = metaData.isValid(); + Log.i(logTag, "valid: " + valid); + if (!valid) { + //setStatusAbnormal(); + return false; + } + + doPersist(metaData); + setDashBoard(metaData); + //setStatusNormal(); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + private boolean doSendMessage(String message) { + Log.v(logTag, ("Activity send message: " + message)); + return true; + } + + private void doCalcBasicData(String data) { + byte[] bytes = ByteUtils.hexStrToBytes(data.substring(0, data.length() - 4)); + switch (bytes[7] & 0xff) { + case Constant.Command.COMMAND_26: + metaData.setMakerId(getMakerId(bytes)); + metaData.setSensorNo(getSensorNo(bytes)); + metaData.setSensorNoRadix(getSensorNoRadix(bytes)); + setMakerNoView(metaData.getMakerId()); + setSensorNoView(Utils.getSensorNoShow(metaData.getSensorNo())); + Log.e(logTag, "sensorNo: " + metaData.getSensorNo()); + PersistHelper.genItem(Integer.valueOf(metaData.getSensorNo()), String.valueOf(this.baudRate)); + //mPresenter.write(genCmd(metaData.getSensorNoRadix(), Constant.Command.COMMAND_27)); + break; + case Constant.Command.COMMAND_28: + mPresenter.write(genCmd(metaData.getSensorNoRadix(), Constant.Command.COMMAND_30)); + break; + case Constant.Command.COMMAND_31: + metaData.setEggNo(getEggNo(bytes)); + setEggNoView(metaData.getEggNo()); + PersistHelper.saveEggID(metaData.getEggNo()); + mPresenter.write(genCmd(metaData.getSensorNoRadix(), Constant.Command.COMMAND_3E)); + break; + case Constant.Command.COMMAND_3F: + metaData.setEggType(getEggType(bytes)); + setEggTypeView(metaData.getEggType()); + PersistHelper.saveEggType(metaData.getEggType()); + mPresenter.write(genCmd(metaData.getSensorNoRadix(), Constant.Command.COMMAND_34)); + break; + case Constant.Command.COMMAND_35: + metaData.setConeNo(getConeNo(bytes)); + setConeNoView(metaData.getConeNo()); + PersistHelper.saveConeNo(metaData.getConeNo()); + Log.i(logTag, "sensorNoRadix: " + metaData.getSensorNoRadix()); + mPresenter.write(genCmd(metaData.getSensorNoRadix(), Constant.Command.COMMAND_38)); + break; + case Constant.Command.COMMAND_39: + metaData.setConeUsedTimes(getConeUsedTimes(bytes)); + setConeUsedTimesView(metaData.getConeUsedTimes()); + PersistHelper.saveConeUsedTimes(metaData.getConeUsedTimes()); + break; + } + } + + private int getMakerId(byte[] bytes) { + int i = ((bytes[4] & 0xff) << 8) | (bytes[5] & 0xff); + String s = "0000".concat(String.valueOf(i)); + String s2 = s.substring(s.length() - 4); + return Integer.valueOf(s2.substring(0, 1)); + } + + private String getSensorNo(byte[] bytes) { + int no = ((bytes[2] & 0xff) * 100 + (bytes[3] & 0xff)) * 10000 + ((bytes[4] & 0xff) << 8) + (bytes[5] & 0xff); + String s = "00000000".concat(String.valueOf(no)); + return s.substring(s.length() - 8); + } + + private String getSensorNoRadix(byte[] bytes) { + int len = 4; + byte[] dest = new byte[len]; + System.arraycopy(bytes, 2, dest, 0, len); + return ByteUtils.bytesToHexStr(dest); + } + + private String getEggNo(byte[] bytes) { + int len = bytes[8]; + byte[] dest = new byte[len]; + System.arraycopy(bytes, 9, dest, 0, len); + ByteUtils.bytesToAscii(dest); + return ByteUtils.bytesToAscii(dest); + } + + private String getEggType(byte[] bytes) { + int len = bytes[8]; + byte[] dest = new byte[len]; + System.arraycopy(bytes, 9, dest, 0, len); + ByteUtils.bytesToAscii(dest); + return ByteUtils.bytesToAscii(dest); + } + + private String getConeNo(byte[] bytes) { + int len = bytes[8]; + byte[] dest = new byte[len]; + System.arraycopy(bytes, 9, dest, 0, len); + ByteUtils.bytesToAscii(dest); + return ByteUtils.bytesToAscii(dest); + } + + private String getConeUsedTimes(byte[] bytes) { + int len = bytes[8]; + byte[] dest = new byte[len]; + System.arraycopy(bytes, 9, dest, 0, len); + ByteUtils.bytesToAscii(dest); + return ByteUtils.bytesToAscii(dest); + } + + private void clearDashBoard() { + mDashBoardTemperature.setSecondText(DEFAULT_VALUE); + mDashBoardHumidity.setSecondText(DEFAULT_VALUE); + mDashBoardInnerPressure.setSecondText(DEFAULT_VALUE); + mDashBoardOuterPressure.setSecondText(DEFAULT_VALUE); + mDashBoardDiffPressure.setSecondText(DEFAULT_VALUE); + ((TextView) (findViewById(R.id.tv_20degree_humidity))).setText(DEFAULT_VALUE); + ((TextView) (findViewById(R.id.tv_20degree_inner_press))).setText(DEFAULT_VALUE); + ((TextView) (findViewById(R.id.tv_maker))).setText(DEFAULT_VALUE); + ((TextView) (findViewById(R.id.tv_sensor_no))).setText(DEFAULT_VALUE); + ((TextView) (findViewById(R.id.tv_egg_no))).setText(DEFAULT_VALUE); + ((TextView) (findViewById(R.id.tv_egg_type))).setText(DEFAULT_VALUE); + ((TextView) (findViewById(R.id.tv_cone_no))).setText(DEFAULT_VALUE); + ((TextView) (findViewById(R.id.tv_cone_used_times))).setText(DEFAULT_VALUE); + } + + private void setDashBoard(MetaData metaData) { + boolean isNormal = true; + if (thresholdBean == null) { + Log.i(logTag, "thresholdBean is null"); + + } + if (metaData.getTemperature() < Float.valueOf(thresholdBean.getTemperatureFloor()) || metaData.getTemperature() > Float.valueOf(thresholdBean.getTemperatureCeiling())) { + isNormal = false; + mDashBoardTemperature.setSecondText(metaData.getTemperature(), (false)); + } else { + mDashBoardTemperature.setSecondText(metaData.getTemperature(), (true)); + } + + if (metaData.getHumidity() < Float.valueOf(thresholdBean.getHumidityFloor()) || metaData.getHumidity() > Float.valueOf(thresholdBean.getHumidityCeiling())) { + isNormal = false; + mDashBoardHumidity.setSecondText(metaData.getHumidity(), (false)); + } else { + mDashBoardHumidity.setSecondText(metaData.getHumidity(), (true)); + } + + if (metaData.getInnerPressure() < Float.valueOf(thresholdBean.getInnerPressureFloor()) || metaData.getInnerPressure() > Float.valueOf(thresholdBean.getInnerPressureCeiling())) { + isNormal = false; + mDashBoardInnerPressure.setSecondText(metaData.getInnerPressure(), (false)); + } else { + mDashBoardInnerPressure.setSecondText(metaData.getInnerPressure(), (true)); + } + + if (metaData.getOuterPressure() < Float.valueOf(thresholdBean.getOuterPressureFloor()) || metaData.getOuterPressure() > Float.valueOf(thresholdBean.getOuterPressureCeiling())) { + isNormal = false; + mDashBoardOuterPressure.setSecondText(metaData.getOuterPressure(), (false)); + } else { + mDashBoardOuterPressure.setSecondText(metaData.getOuterPressure(), (true)); + } + + if (metaData.getDiffPressure() < Float.valueOf(thresholdBean.getDiffPressureFloor()) || metaData.getDiffPressure() > Float.valueOf(thresholdBean.getDiffPressureCeiling())) { + isNormal = false; + mDashBoardDiffPressure.setSecondText(metaData.getDiffPressure(), (false)); + } else { + mDashBoardDiffPressure.setSecondText(metaData.getDiffPressure(), (true)); + } + + ((TextView) (findViewById(R.id.tv_20degree_humidity))).setText(new DecimalFormat(FLOAT_TYPE).format(metaData.getDegree20Humidity())); + ((TextView) (findViewById(R.id.tv_20degree_inner_press))).setText(new DecimalFormat(FLOAT_TYPE).format(metaData.getDegree20Pressure())); + + if (isNormal) { + setStatusNormal(); + } else { + setStatusAbnormal(); + } + } + + private void setStatusNormal() { + ((TextView) (findViewById(R.id.tv_main_status_normal))).setTextColor(getResources().getColor(R.color.param_black_color)); + findViewById(R.id.tv_main_status_normal_round).setBackgroundResource(R.drawable.shape_status_green_round); + ((TextView) (findViewById(R.id.tv_main_status_err))).setTextColor(getResources().getColor(R.color.status_grey)); + findViewById(R.id.tv_main_status_err_round).setBackgroundResource(R.drawable.shape_status_grey_round); + } + + private void setStatusAbnormal() { + ((TextView) (findViewById(R.id.tv_main_status_normal))).setTextColor(getResources().getColor(R.color.status_grey)); + findViewById(R.id.tv_main_status_normal_round).setBackgroundResource(R.drawable.shape_status_grey_round); + ((TextView) (findViewById(R.id.tv_main_status_err))).setTextColor(getResources().getColor(R.color.param_black_color)); + findViewById(R.id.tv_main_status_err_round).setBackgroundResource(R.drawable.shape_status_red_round); + } + + private void resetStatus() { + ((TextView) (findViewById(R.id.tv_main_status_normal))).setTextColor(getResources().getColor(R.color.param_grey_color)); + findViewById(R.id.tv_main_status_normal_round).setBackgroundResource(R.drawable.shape_status_grey_round); + ((TextView) (findViewById(R.id.tv_main_status_err))).setTextColor(getResources().getColor(R.color.status_grey)); + findViewById(R.id.tv_main_status_err_round).setBackgroundResource(R.drawable.shape_status_grey_round); + } + + private void readBtnToOriginState() { + findViewById(R.id.btn_read).setEnabled(true); + findViewById(R.id.btn_read).setBackgroundResource(R.drawable.bg_start_btn_new); + ((Button) findViewById(R.id.btn_read)).setText(R.string.start_test); + } + + private void readBtnToStopState() { + findViewById(R.id.btn_read).setEnabled(true); + findViewById(R.id.btn_read).setBackgroundResource(R.drawable.bg_stop_btn_new); + ((Button) findViewById(R.id.btn_read)).setText(R.string.stop_test); + } + + private void readBtnToStartingState() { + findViewById(R.id.btn_read).setBackgroundResource(R.drawable.bg_read_btn_starting); + ((Button) findViewById(R.id.btn_read)).setText(R.string.read_btn_starting); + findViewById(R.id.btn_read).setEnabled(false); + } + + private void readBtnToState(boolean isOpen) { + findViewById(R.id.btn_read).setEnabled(true); + findViewById(R.id.btn_read).setBackgroundResource(isOpen ? R.drawable.bg_stop_btn_new : R.drawable.bg_start_btn_new); + ((Button) findViewById(R.id.btn_read)).setText(isOpen ? R.string.stop_test : R.string.start_test); + } + + private void doPersist(MetaData metaData) { + PersistHelper.save(metaData.getTemperature(), Constant.Command.COMMAND_29); + PersistHelper.save(metaData.getInnerPressure(), Constant.Command.COMMAND_2A); + PersistHelper.save(metaData.getHumidity(), Constant.Command.COMMAND_2B); + PersistHelper.save(metaData.getOuterPressure(), Constant.Command.COMMAND_2C); + PersistHelper.save(metaData.getDiffPressure(), Constant.Command.COMMAND_2D); + PersistHelper.save(metaData.getDegree20Humidity(), Constant.Command.COMMAND_2E); + PersistHelper.save(metaData.getDegree20Pressure(), Constant.Command.COMMAND_2F); + } +} + diff --git a/app/src/main/java/com/handset/serialportsensor/activity/PasswordResetActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/PasswordResetActivity.java new file mode 100644 index 0000000..03b5909 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/PasswordResetActivity.java @@ -0,0 +1,77 @@ +package com.handset.serialportsensor.activity; + +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.account.AccountManager; +import com.handset.serialportsensor.utils.SPUtils; + +public class PasswordResetActivity extends BaseActivity { + + private EditText etOriginal; + private EditText etNew; + private EditText etRepeat; + LinearLayout ll_old_pas; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_reset_password); + initView(); + } + + boolean showAdmin; + + private void initView() { + initTitle(); + etOriginal = findViewById(R.id.et_original_password); + etNew = findViewById(R.id.et_new_password); + etRepeat = findViewById(R.id.et_repeat_password); + ll_old_pas = findViewById(R.id.ll_old_pas); + TextView btnSave = findViewById(R.id.btn_save); + btnSave.setOnClickListener((View view) -> save()); + showAdmin = "admin".equals(AccountManager.get().getUserId()); + ll_old_pas.setVisibility(showAdmin ? View.VISIBLE : View.GONE); + } + + private void save() { + String pwdOld = etOriginal.getText().toString(); + String etn = etNew.getText().toString(); + String etR = etRepeat.getText().toString(); + if (AccountManager.get().isLogin()) { + if (showAdmin) { + String pwdOldTrue = SPUtils.getInstance(this).get("admin"); + if (!TextUtils.isEmpty(pwdOldTrue) && !pwdOld.equals(pwdOldTrue)) { + Toast.makeText(this, getString(R.string.old_pwd_wrong), Toast.LENGTH_SHORT).show(); + return; + } + } + if (TextUtils.isEmpty(etn) || TextUtils.isEmpty(etR)) { + Toast.makeText((this), getString(R.string.new_pwd_empty), Toast.LENGTH_SHORT).show(); + } else if (!etn.equals(etR)) { + Toast.makeText((this), getString(R.string.new_pwd_not_same), Toast.LENGTH_SHORT).show(); + } else { + SPUtils.getInstance(this).put("admin", etR); + Toast.makeText((this), getString(R.string.pwd_change_success), Toast.LENGTH_SHORT).show(); + finish(); + } + } else { + Toast.makeText((this), getString(R.string.pwd_login_first), Toast.LENGTH_SHORT).show(); + } + } + + private void initTitle() { + ImageView ivBack = findViewById(R.id.title_back); + ivBack.setVisibility(View.VISIBLE); + ivBack.setOnClickListener((View view) -> finish()); + TextView tvTitle = findViewById(R.id.title_text); + tvTitle.setText(R.string.reset_password_title); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/SPKey.java b/app/src/main/java/com/handset/serialportsensor/activity/SPKey.java new file mode 100644 index 0000000..4c86626 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/SPKey.java @@ -0,0 +1,21 @@ +package com.handset.serialportsensor.activity; + +public interface SPKey { + + String SU_PATH = "su_path"; + String SERIAL_PORT = "serial_port"; + String BAUD_RATE = "baud_rate"; + String DATA_BITS = "data_bits"; + String CHECK_DIGIT = "check_digit"; + String STOP_BIT = "stop_bit"; + String FLOW_CONTROL = "flow_control"; + + String SETTING_RECEIVE_TYPE = "receive_type"; + String SETTING_RECEIVE_SHOW_TIME = "setting_receive_show_time"; + String SETTING_RECEIVE_SHOW_SEND = "setting_receive_show_send"; + + String SETTING_SEND_TYPE = "setting_send_type"; + String SETTING_SEND_REPEAT = "setting_send_repeat"; + String SETTING_SEND_DURING = "setting_send_during"; + String SEND_HISTORY = "send_history"; +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/SensorSettingsActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/SensorSettingsActivity.java new file mode 100644 index 0000000..908c302 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/SensorSettingsActivity.java @@ -0,0 +1,441 @@ +package com.handset.serialportsensor.activity; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.handset.serialportlib.ByteUtils; +import com.handset.serialportlib.CRCUtils; +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.account.AccountManager; +import com.handset.serialportsensor.adapter.SettingsAdapter; +import com.handset.serialportsensor.bean.RawData; +import com.handset.serialportsensor.bean.SettingsItem; +import com.handset.serialportsensor.bean.TestRecordsTotal; +import com.handset.serialportsensor.constant.Constant; +import com.handset.serialportsensor.presenter.SurfaceContract; +import com.handset.serialportsensor.presenter.SurfacePresenter; +import com.handset.serialportsensor.utils.DateUtils; +import com.handset.serialportsensor.utils.ToastHelper; +import com.handset.serialportsensor.utils.ExcelMa; +import com.handset.serialportsensor.utils.PersistHelper; +import com.handset.serialportsensor.view.ExportProgressDialog; + +import org.kymjs.kjframe.KJDB; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static com.handset.serialportsensor.utils.DateStyle.YYYY_MM_DD_HH_MM; + +public class SensorSettingsActivity extends BaseActivity implements SettingsAdapter.OnItemClickListener, SurfaceContract.ISerialView { + private final static String logTag = "HANDSET-JE002-EX"; + + private String sensorId; + + private Integer baudRate; + + private AlertDialog resetDialog; + + private ExcelMa mExcelMa = new ExcelMa(); + + private SurfacePresenter mPresenter = new SurfacePresenter((this)); + + private int[] iconsAdmin = new int[]{ + R.mipmap.ic_settings1, R.mipmap.ic_settings2, R.mipmap.ic_settings3, + R.mipmap.ic_settings4, R.mipmap.ic_settings5, R.mipmap.ic_settings6, R.mipmap.ic_settings7, + R.mipmap.ic_settings8, R.mipmap.ic_settings9, R.mipmap.ic_settings9, R.mipmap.ic_settings9 + }; + private String[] namesAdmin = new String[]{"波特率设置", "阈值设置", "弹筒信息", "数据导出", "数据恢复", "设置系统时间", "重置密码"}; + private int[] mPositionAdmin = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + + private int[] iconsRoot = new int[]{ + R.mipmap.ic_settings7, R.mipmap.ic_settings8, R.mipmap.img_right, + R.mipmap.ic_settings2, R.mipmap.ic_settings9 + }; + + private String[] namesRoot = new String[]{"重置密码", "恢复传感器出厂设置", "第三方传感器弹筒信息开关", "传感器ID设置", "查看操作日志"}; + private int[] mPositionRoot = new int[]{6, 7, 8, 9, 10}; + + public static void open(Integer baudRate, Integer role, String sensorId, Context context) { + Intent intent = new Intent(context, SensorSettingsActivity.class); + intent.putExtra(Constant.ROLE_KEY, role); + Log.e(logTag, "sensorId 444: " + sensorId); + intent.putExtra(Constant.BAUD_RATE, baudRate); + intent.putExtra(Constant.SENSOR_ID, sensorId); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_sensor_settings); + initView(); + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + private void initView() { + initTitle(); + RecyclerView recyclerView = findViewById(R.id.recycle_view); + recyclerView.setLayoutManager(new LinearLayoutManager((this))); + Intent intent = getIntent(); + int role = Constant.NOT_CONNECTED_ROLE; + if (intent != null) { + role = intent.getIntExtra(Constant.ROLE_KEY, Constant.NOT_CONNECTED_ROLE); + baudRate = intent.getIntExtra(Constant.BAUD_RATE, (38400)); + sensorId = intent.getStringExtra(Constant.SENSOR_ID); + Log.i(logTag, ("hex string sensorId: " + sensorId)); + } + ArrayList items = new ArrayList<>(); + Log.i(logTag, ("accountId: " + AccountManager.get().getUserId())); + if (AccountManager.get().getUserId().equals("admin")) { + for (int i = 0; i < namesAdmin.length; i++) { + items.add(new SettingsItem(namesAdmin[i], iconsAdmin[i], mPositionAdmin[i])); + } + } else { + for (int i = 0; i < namesRoot.length; i++) { + items.add(new SettingsItem(namesRoot[i], iconsRoot[i], mPositionRoot[i])); + } + } + + SettingsAdapter adapter = new SettingsAdapter(items, role); + adapter.setOnItemClickListener(this); + recyclerView.setAdapter(adapter); + + findViewById(R.id.btn_logout).setOnClickListener((View v) -> { + AccountManager.get().logout(); + finish(); + startActivity(new Intent((SensorSettingsActivity.this), LoginActivity.class)); + }); + } + + private void initTitle() { + ImageView ivBack = findViewById(R.id.title_back); + ivBack.setVisibility(View.VISIBLE); + ivBack.setOnClickListener((View view) -> finish()); + TextView tvTitle = findViewById(R.id.title_text); + tvTitle.setText(R.string.sensor_settings_title); + } + + @Override + public void onItemClick(View view, int position) { + int id = mPositionAdmin[position]; + if (AccountManager.get().getUserId().equals("root")) { + id = mPositionRoot[position]; + } + + Intent intent; + switch (id) { + case 0: + intent = new Intent((SensorSettingsActivity.this), BaudRateSettingActivity.class); + intent.putExtra(Constant.BAUD_RATE, baudRate); + intent.putExtra(Constant.SENSOR_ID, sensorId); + startActivity(intent); + break; + case 1: + startActivity(new Intent((SensorSettingsActivity.this), ThresholdActivity.class)); + break; + case 2: + intent = new Intent((SensorSettingsActivity.this), ConeSettingActivity.class); + Log.e(logTag, "sensorId 222: " + sensorId); + intent.putExtra(Constant.BAUD_RATE, baudRate); + intent.putExtra(Constant.SENSOR_ID, sensorId); + startActivity(intent); + break; + case 3: + //数据导出 + confirmExport(); + break; + case 4: + //数据恢复 + startActivity(new Intent((SensorSettingsActivity.this), DataRecoverActivity.class)); + break; + case 5: + startActivity(new Intent(Settings.ACTION_DATE_SETTINGS)); + break; + case 6: + startActivity(new Intent((SensorSettingsActivity.this), PasswordResetActivity.class)); + break; + case 7: + ToastHelper.showResetSensorDialog((this), new ToastHelper.OnDialogClickListener() { + @Override + public void onOKClickListener(View view) { + reset(); + } + + @Override + public void onCancelClickListener(View view) { + + } + }); + break; + case 8: + if (AccountManager.get().getUserId().equals("root")) { + startActivity(new Intent((SensorSettingsActivity.this), ThirdSensorSettingsActivity.class)); + } else { + Toast.makeText((this), "请登录root 后在操作", Toast.LENGTH_SHORT).show(); + } + break; + case 9: + if (AccountManager.get().getUserId().equals("root")) { + intent = new Intent((SensorSettingsActivity.this), ChangeSensorIdSettingsActivity.class); + intent.putExtra(Constant.BAUD_RATE, baudRate); + intent.putExtra(Constant.SENSOR_ID, sensorId); + startActivityForResult(intent, (10001)); + } else { + Toast.makeText((this), "请登录root 后在操作", Toast.LENGTH_SHORT).show(); + } + break; + case 10: + if (AccountManager.get().getUserId().equals("root")) { + startActivityForResult(new Intent((SensorSettingsActivity.this), ViewOperateLogListActivity.class), 10001); + } else { + Toast.makeText((this), "请登录root 后在操作", Toast.LENGTH_SHORT).show(); + } + break; + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 10001) { + if (resultCode == RESULT_OK && data != null) { + String sensorId = data.getStringExtra(Constant.SENSOR_ID); + sendSensorId(sensorId); + } + } + } + + private void sendSensorId(String sensorId) { + StringBuilder sb = new StringBuilder(this.sensorId); + sb.append("00").append("80").append("04").append(sensorId); + String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); + Log.i(logTag, "sensor no set: cooked: " + cooked); + Log.i(logTag, "sensor no set: cooked 2: " + Arrays.toString(cooked.getBytes())); + mPresenter.write(cooked); + } + + private void openAssignFolder(final String times) { + mExportProgressDialog = null; + new Thread(() -> { + List testRecordsTotals = KJDB.getDefaultInstance().findAllByWhere(TestRecordsTotal.class, "1=1"); + mExcelMa.write(testRecordsTotals, new PersistHelper.ExportCallback() { + @Override + public void exportProgress(int counts, int remain) { + Log.d(logTag, "exportProgress [counts, remain]:" + counts + " " + remain); + showExportProgress(counts, remain); + } + + @Override + public void finish(int counts, int remain) { + if (remain != 0) { + showCancelTip(); + } + } + }, times); + }).start(); + } + + //数据导出确认 + private void confirmExport() { + runOnUiThread(() -> { + dismissDialog(null); + final String items = DateUtils.formatMilliesTimestamp(System.currentTimeMillis(), YYYY_MM_DD_HH_MM); + final String name = "检测结果(" + items + ").xlsx"; + String alarm = "导出数据到 内部存储/htjc/sensor/export/" + name + ""; + AlertDialog a = ToastHelper.showChooseDialogNoShow( + getString(R.string.import_out_confirm), + R.mipmap.ic_exclamation_mark, + alarm, + getResources().getColor(R.color.button), + getString(R.string.confirm), getString(R.string.cancel), + (SensorSettingsActivity.this), + new ToastHelper.OnDialogClickListener() { + @Override + public void onOKClickListener(View view) { + openAssignFolder(items); + } + + @Override + public void onCancelClickListener(View view) { + } + }); + showDialog(a); + }); + } + + private void showCancelTip() { + runOnUiThread(() -> { + AlertDialog alertDialog = ToastHelper.showTipDialogNoShow((SensorSettingsActivity.this), R.mipmap.chuchang_gray, R.string.cancel); + showDialog(alertDialog); + disMissDialogDelay(alertDialog, (3000)); + }); + } + + ExportProgressDialog mExportProgressDialog; + + private void showExportProgress(final int count, final int remain) { + if (mExportProgressDialog == null) { + runOnUiThread(() -> { + mExportProgressDialog = new ExportProgressDialog(); + mExportProgressDialog.showExportDialogNoShow( + (SensorSettingsActivity.this), + (View view) -> mExcelMa.stopExport(), + count, + remain, + getString(R.string.importing_to_excel_file), + getString(R.string.import_out) + ); + showDialog(mExportProgressDialog.mAlertDialog); + }); + } else { + mExportProgressDialog.update(this, count, remain); + } + } + + //正在设置 + private void showSettingDialog() { + runOnUiThread(() -> { + resetDialog = ToastHelper.showTipDialog((SensorSettingsActivity.this), R.mipmap.ic_setting, R.string.reset_tip); + disMissDialogDelay(resetDialog, (10000)); + } + ); + } + + private Handler mHandler = new Handler(); + private Runnable mRunnable; + + @Override + public void disMissDialogDelay(final AlertDialog alertDialog, int delayMillis) { + mRunnable = () -> { + Log.i(logTag, "SensorSettingsActivity, disMissDialogDelay"); + mPresenter.close(); + dismissDialogD(alertDialog); + }; + mHandler.postDelayed(mRunnable, delayMillis); + } + + private void reset() { + showSettingDialog(); + new Thread(() -> { + Looper.prepare(); + new Handler().postDelayed(() -> mPresenter.open(baudRate), (500)); + Looper.loop(); + } + ).start(); + + handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_49, (3000)); + } + + @SuppressLint("HandlerLeak") + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + if (msg.what == Constant.Command.COMMAND_49) {//恢复出厂值 + StringBuilder sb = new StringBuilder(sensorId); + sb.append("00").append("49").append("00"); + String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); + Log.i(logTag, "SensorSettingsActivity, cooked: " + cooked); + mPresenter.write(cooked); + } + } + }; + + @Override + public void onSerialOpen(boolean isOpen) { + + } + + @Override + public void onSerialBaudRate(Integer baudRate) { + + } + + @Override + public void onSerialData(RawData rawData) { + if (rawData.getItemType() == RawData.TYPE_RECEIVE) { + Log.i(logTag, "SensorSettingsActivity, onSerialData: " + rawData.getMessage()); + byte[] bytes = ByteUtils.hexStrToBytes(rawData.getMessage()); + Log.i(logTag, "SensorSettingsActivity, onSerialData 2: " + Arrays.toString(bytes)); + if (bytes.length > 8) { + if ((bytes[6] & 0xff) == 0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_4A) { + Log.i(logTag, "SensorSettingsActivity, onSerialData, 0x49 feedback: " + rawData.getMessage()); + mPresenter.close(); + dismissDialog(resetDialog); + mHandler.removeCallbacks(mRunnable); + restoreToFactorySuccess(); + } else { + mPresenter.close(); + dismissDialog(resetDialog); + mHandler.removeCallbacks(mRunnable); + restoreToFactoryFail(); + } + } + } + } + + @Override + public void onSerialError(Integer errorCode) { + + } + + //设置成功 + private void restoreToFactorySuccess() { + runOnUiThread(() -> { + disMissLoadingDialog(resetDialog); + ToastHelper.showSubmitDialog( + getString(R.string.restore_factory_success), + R.mipmap.img_right, + getString(R.string.go_back_init_screen_content), + getResources().getColor(R.color.blue_button_bg), + getString(R.string.btn_ensure), + (SensorSettingsActivity.this), + (View view) -> finish() + ); + }); + } + + //设置失败 + private void restoreToFactoryFail() { + runOnUiThread(() -> { + disMissLoadingDialog(resetDialog); + ToastHelper.showSubmitDialog( + getString(R.string.restore_factory_failed), + R.mipmap.img_cross, + getString(R.string.go_back_init_screen_content), + getResources().getColor(R.color.button), + getString(R.string.btn_ensure), + (SensorSettingsActivity.this), + (View view) -> { + } + ); + } + ); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/SplashActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/SplashActivity.java new file mode 100644 index 0000000..e229b9a --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/SplashActivity.java @@ -0,0 +1,40 @@ +package com.handset.serialportsensor.activity; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; + +import com.handset.serialportsensor.R; + +import io.reactivex.Observable; +import io.reactivex.disposables.Disposable; + +import java.util.concurrent.TimeUnit; + +public class SplashActivity extends AppCompatActivity { + + private Disposable mDisposable; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_splash); + mDisposable = Observable + .timer((1), TimeUnit.SECONDS) + .subscribe(this::jumpToMain, Throwable::printStackTrace); + } + + @SuppressWarnings(value = "unused") + private void jumpToMain(Long aLong) { + startActivity(new Intent((this), Main2Activity.class)); + finish(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mDisposable != null) { + mDisposable.dispose(); + } + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/ThirdSensorSettingsActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/ThirdSensorSettingsActivity.java new file mode 100644 index 0000000..50b945d --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/ThirdSensorSettingsActivity.java @@ -0,0 +1,41 @@ +package com.handset.serialportsensor.activity; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.CompoundButton; +import android.widget.ImageView; +import android.widget.Switch; +import android.widget.TextView; + +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.account.AccountManager; +import com.handset.serialportsensor.utils.SPUtils; + +/** + * Created by zy on 2019/2/23. + */ + +public class ThirdSensorSettingsActivity extends AppCompatActivity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_third_sensor_settings); + Switch sw_sensor = (Switch) findViewById(R.id.sw_sensor); + boolean sensor_third_enable = SPUtils.getInstance(this).get("sensor_third_enable", false); + sw_sensor.setChecked(sensor_third_enable); + sw_sensor.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + SPUtils.getInstance(ThirdSensorSettingsActivity.this).put("sensor_third_enable", isChecked); + AccountManager.get().putUserData("sensor_third_enable", isChecked + ""); + } + }); + TextView tvTitle = findViewById(R.id.title_text); + ImageView ivBack = findViewById(R.id.title_back); + tvTitle.setText("第三方传感器弹筒信息开关"); + ivBack.setVisibility(View.VISIBLE); + ivBack.setOnClickListener((View v) -> ThirdSensorSettingsActivity.this.finish()); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/ThresholdActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/ThresholdActivity.java new file mode 100644 index 0000000..ac82ace --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/ThresholdActivity.java @@ -0,0 +1,264 @@ +package com.handset.serialportsensor.activity; + +import android.content.Context; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.text.TextUtils; +import android.view.MotionEvent; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.gson.Gson; +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.account.AccountManager; +import com.handset.serialportsensor.bean.ThresholdBean; +import com.handset.serialportsensor.constant.Constant; +import com.handset.serialportsensor.utils.SpUtil; + +public class ThresholdActivity extends AppCompatActivity { + private EditText etTempLow; + private EditText etTempHigh; + private EditText etHumLow; + private EditText etHumHigh; + private EditText etPressureLow1; + private EditText etPressureHigh1; + private EditText etPressureLow2; + private EditText etPressureHigh2; + + + private EditText etDiffPressureLow; + private EditText etDiffPressureHigh; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_threshold); + initView(); + setDefaultValue(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + InputMethodManager im = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + if(im != null) { + View view = getCurrentFocus(); + if(view != null) { + im.hideSoftInputFromWindow(getCurrentFocus().getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + } + return super.onTouchEvent(event); + } + + private void initView() { + initTitle(); + } + + private void initTitle() { + ImageView ivBack = findViewById(R.id.title_back); + ivBack.setVisibility(View.VISIBLE); + ivBack.setOnClickListener((View view) -> finish()); + TextView tvTitle = findViewById(R.id.title_text); + tvTitle.setText(R.string.set_threshold_title); + etTempLow = findViewById(R.id.et_temp_low); + etTempHigh = findViewById(R.id.et_temp_high); + etHumLow = findViewById(R.id.et_humidity_low); + etHumHigh = findViewById(R.id.et_humidity_high); + etPressureLow1 = findViewById(R.id.et_pressure1_low); + etPressureHigh1 = findViewById(R.id.et_pressure1_high); + etPressureLow2 = findViewById(R.id.et_pressure2_low); + etPressureHigh2 = findViewById(R.id.et_pressure2_high); + etDiffPressureHigh = findViewById(R.id.et_pressure_yahcha_high); + etDiffPressureLow = findViewById(R.id.et_pressure_yacha_low); + findViewById(R.id.btn_save).setOnClickListener((View view) -> save()); + } + + private void save() { + if (check()) { + ThresholdBean bean = new ThresholdBean(); + bean.setTemperatureFloor(etTempLow.getText().toString()); + bean.setTemperatureCeiling(etTempHigh.getText().toString()); + bean.setHumidityFloor(etHumLow.getText().toString()); + bean.setHumidityCeiling(etHumHigh.getText().toString()); + bean.setInnerPressureFloor(etPressureLow1.getText().toString()); + bean.setInnerPressureCeiling(etPressureHigh1.getText().toString()); + bean.setOuterPressureFloor(etPressureLow2.getText().toString()); + bean.setOuterPressureCeiling(etPressureHigh2.getText().toString()); + bean.setDiffPressureFloor(etDiffPressureLow.getText().toString()); + bean.setDiffPressureCeiling(etDiffPressureHigh.getText().toString()); + SpUtil.put(this, Constant.THRESHOLD_KEY, new Gson().toJson(bean)); + + Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show(); + AccountManager.get().putUserData("ThresholdBean", "ThresholdBean"); + finish(); + } + } + + private boolean check() { + if (!checkDataFormat(etTempLow.getText().toString())) { + Toast.makeText(this, "温度下限格式不正确", Toast.LENGTH_SHORT).show(); + return false; + } else if (!checkDataFormat(etTempHigh.getText().toString())) { + Toast.makeText(this, "温度上限格式不正确", Toast.LENGTH_SHORT).show(); + return false; + } else if (!checkDataFormat(etHumLow.getText().toString())) { + Toast.makeText(this, "湿度下限格式不正确", Toast.LENGTH_SHORT).show(); + return false; + } else if (!checkDataFormat(etHumHigh.getText().toString())) { + Toast.makeText(this, "湿度上限格式不正确", Toast.LENGTH_SHORT).show(); + return false; + } else if (!checkDataFormat(etPressureLow1.getText().toString())) { + Toast.makeText(this, "内压下限格式不正确", Toast.LENGTH_SHORT).show(); + return false; + } else if (!checkDataFormat(etPressureHigh1.getText().toString())) { + Toast.makeText(this, "内压上限格式不正确", Toast.LENGTH_SHORT).show(); + return false; + } else if (!checkDataFormat(etPressureLow2.getText().toString())) { + Toast.makeText(this, "外压下限格式不正确", Toast.LENGTH_SHORT).show(); + return false; + } else if (!checkDataFormat(etPressureHigh2.getText().toString())) { + Toast.makeText(this, "外压上限格式不正确", Toast.LENGTH_SHORT).show(); + return false; + } else if (!checkDataFormat(etDiffPressureLow.getText().toString())) { + Toast.makeText(this, "压差下限格式不正确", Toast.LENGTH_SHORT).show(); + return false; + } else if (!checkDataFormat(etDiffPressureHigh.getText().toString())) { + Toast.makeText(this, "压差上限格式不正确", Toast.LENGTH_SHORT).show(); + return false; + } + + if (!between(checkDataFormatF(etTempHigh.getText().toString()), 85f, -45f) + || !between(checkDataFormatF(etTempLow.getText().toString()), 85f, -45f)) { + Toast.makeText(this, "温度范围只能输入 -45~85", Toast.LENGTH_SHORT).show(); + return false; + } + + + if (!between(checkDataFormatF(etHumHigh.getText().toString()), 100f, 0f) + || !between(checkDataFormatF(etHumLow.getText().toString()), 100f, 0f)) { + Toast.makeText(this, "湿度范围只能输入 0~100", Toast.LENGTH_SHORT).show(); + return false; + } + + if (!between(checkDataFormatF(etPressureHigh1.getText().toString()), 200f, 0f) + || !between(checkDataFormatF(etPressureLow1.getText().toString()), 200f, 0f) + || !between(checkDataFormatF(etPressureHigh2.getText().toString()), 200f, 0f) + || !between(checkDataFormatF(etPressureLow2.getText().toString()), 200f, 0f)) { + Toast.makeText(this, "压力范围只能输入 0~200", Toast.LENGTH_SHORT).show(); + return false; + } + + if (!between(checkDataFormatF(etDiffPressureHigh.getText().toString()), 30f, -20f) + || !between(checkDataFormatF(etDiffPressureLow.getText().toString()), 30f, -20f)) { + Toast.makeText(this, "压差范围只能输入 -20~30", Toast.LENGTH_SHORT).show(); + return false; + } + + + if (!compareBS(etTempHigh.getText().toString(), etTempLow.getText().toString())) { + Toast.makeText(this, "湿度上限不能低于下限", Toast.LENGTH_SHORT).show(); + return false; + } + if (!compareBS(etHumHigh.getText().toString(), etHumLow.getText().toString())) { + Toast.makeText(this, "湿度上限不能低于下限", Toast.LENGTH_SHORT).show(); + return false; + } + if (!compareBS(etPressureHigh1.getText().toString(), etPressureLow1.getText().toString())) { + Toast.makeText(this, "内压上限不能低于下限", Toast.LENGTH_SHORT).show(); + return false; + } + if (!compareBS(etPressureHigh2.getText().toString(), etPressureLow2.getText().toString())) { + Toast.makeText(this, "外压上限不能低于下限", Toast.LENGTH_SHORT).show(); + return false; + } + if (!compareBS(etDiffPressureHigh.getText().toString(), etDiffPressureLow.getText().toString())) { + Toast.makeText(this, "压差上限不能低于下限", Toast.LENGTH_SHORT).show(); + return false; + } + + return true; + } + + private boolean between(Float f, Float up, Float low) { + if (f == null || up == null || low == null) { + return false; + } + return low <= f && f <= up; + } + + private boolean checkDataFormat(String a) { + return checkDataFormatF(a) != null; + } + + private Float checkDataFormatF(String a) { + if (TextUtils.isEmpty(a)) { + return null; + } + try { + Float f = Float.parseFloat(a); + return f; + } catch (NumberFormatException e) { + e.printStackTrace(); + return null; + } + } + + private boolean compareBS(String bigger, String smaller) { + if (TextUtils.isEmpty(bigger) || TextUtils.isEmpty(smaller)) { + return false; + } + + try { + Float bigErf = Float.parseFloat(bigger); + Float smallErf = Float.parseFloat(smaller); + if (bigErf >= smallErf) { + return true; + } + } catch (NumberFormatException e) { + e.printStackTrace(); + return false; + } + return false; + } + + /** + * 配置默认阈值参数 + */ + + private void setDefaultValue() { + ThresholdBean bean = new ThresholdBean(); + bean.setTemperatureFloor("-40"); + bean.setTemperatureCeiling("65"); + bean.setHumidityFloor("0"); + bean.setHumidityCeiling("100"); + bean.setInnerPressureFloor("80"); + bean.setInnerPressureCeiling("150"); + bean.setOuterPressureFloor("80"); + bean.setOuterPressureCeiling("150"); + bean.setDiffPressureFloor("-20"); + bean.setDiffPressureCeiling("30"); + String bean2 = (String) SpUtil.get(this, Constant.THRESHOLD_KEY, ""); + ThresholdBean bean1 = null; + if (!TextUtils.isEmpty(bean2)) { + bean1 = new Gson().fromJson(bean2, ThresholdBean.class); + } + + if (bean1 != null) { + bean = bean1; + } + etTempLow.setText(bean.getTemperatureFloor()); + etTempHigh.setText(bean.getTemperatureCeiling()); + etHumLow.setText(bean.getHumidityFloor()); + etHumHigh.setText(bean.getHumidityCeiling()); + etPressureLow1.setText(bean.getInnerPressureFloor()); + etPressureHigh1.setText(bean.getInnerPressureCeiling()); + etPressureLow2.setText(bean.getOuterPressureFloor()); + etPressureHigh2.setText(bean.getOuterPressureCeiling()); + etDiffPressureHigh.setText(bean.getDiffPressureCeiling()); + etDiffPressureLow.setText(bean.getDiffPressureFloor()); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/ViewLogActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/ViewLogActivity.java new file mode 100644 index 0000000..7e15307 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/ViewLogActivity.java @@ -0,0 +1,70 @@ +package com.handset.serialportsensor.activity; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.handset.serialportsensor.R; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +/** + * Created by zy on 2019/2/28. + */ + +public class ViewLogActivity extends AppCompatActivity { + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_view_log); + Intent intent = getIntent(); + String filePath = intent.getStringExtra("file_path"); + + TextView tv_log = findViewById(R.id.tv_log); + TextView tvTitle = findViewById(R.id.title_text); + ImageView ivBack = findViewById(R.id.title_back); + tvTitle.setText("操作日志"); + ivBack.setVisibility(View.VISIBLE); + ivBack.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ViewLogActivity.this.finish(); + } + }); + + if (!TextUtils.isEmpty(filePath)) { + String ac = getfileC(filePath); + tv_log.setText(ac); + } + + } + + + private String getfileC(String filePath) { + String c = ""; + File file = new File(filePath); + FileInputStream in; + try { + in = new FileInputStream(file); + int l = (int) file.length(); + byte[] filecontent = new byte[l]; + in.read(filecontent); + in.close(); + c = new String(filecontent); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return c; + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/activity/ViewOperateLogListActivity.java b/app/src/main/java/com/handset/serialportsensor/activity/ViewOperateLogListActivity.java new file mode 100644 index 0000000..efdc677 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/activity/ViewOperateLogListActivity.java @@ -0,0 +1,136 @@ +package com.handset.serialportsensor.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.constraint.ConstraintLayout; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.DividerItemDecoration; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.utils.Slog; +import com.handset.serialportsensor.view.LinearLayoutManagerCus; + +import java.io.File; +import java.util.List; + +import static android.support.v7.widget.DividerItemDecoration.VERTICAL; + +/** + * Created by zy on 2019/2/27. + */ + + +public class ViewOperateLogListActivity extends AppCompatActivity { + RecyclerView mRecyclerView; + MyAdapter myAdapter; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_view_operate_log); + mRecyclerView = findViewById(R.id.recycle_view); + mRecyclerView.setLayoutManager(new LinearLayoutManagerCus(this)); + DefaultItemAnimator animator = new DefaultItemAnimator(); + animator.setRemoveDuration(1000); + mRecyclerView.setItemAnimator(animator); + TextView tvTitle = findViewById(R.id.title_text); + ImageView ivBack = findViewById(R.id.title_back); + tvTitle.setText("操作日志"); + ivBack.setVisibility(View.VISIBLE); + ivBack.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ViewOperateLogListActivity.this.finish(); + } + }); + mRecyclerView.addItemDecoration(new DividerItemDecoration(this, VERTICAL)); + getOperateLog(); + } + + private void getOperateLog() { + List list = Slog.getOperateLogFiles(); + //设置适配器 + if (myAdapter == null) { + myAdapter = new MyAdapter(this, list); + mRecyclerView.setAdapter(myAdapter); + } else { + myAdapter.setDataList(list); + } + } + + static class ViewHolder extends RecyclerView.ViewHolder { + + TextView tvIndex; + TextView tvLog; + ConstraintLayout cl_content; + + public ViewHolder(@NonNull View itemView) { + super(itemView); + tvIndex = itemView.findViewById(R.id.tv_item_index); + tvLog = itemView.findViewById(R.id.tv_name); + cl_content = itemView.findViewById(R.id.cl_content); + } + } + + static class MyAdapter extends RecyclerView.Adapter { + List mDataList; + + private OnItemClickListener mOnItemClickListener; + + Context mContext; + + public MyAdapter(Context context, List mList) { + mContext = context; + this.mDataList = mList; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + return new ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.operate_log_item, null, false)); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder viewHolder, final int i) { + final File file = mDataList.get(i); + viewHolder.tvIndex.setText((i + 1) + ""); + viewHolder.tvLog.setText(file.getName()); + viewHolder.cl_content.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(mContext, ViewLogActivity.class); + intent.putExtra("file_path", file.getAbsolutePath()); + mContext.startActivity(intent); + } + }); + } + + @Override + public int getItemCount() { + return mDataList.size(); + } + + public void setOnItemClickListener(OnItemClickListener onItemClickListener) { + this.mOnItemClickListener = onItemClickListener; + } + + public void setDataList(List dataList) { + mDataList = dataList; + notifyDataSetChanged(); + } + } + + public interface OnItemClickListener { + void onItemClick(View view, int position); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/adapter/HistoryAdapter.java b/app/src/main/java/com/handset/serialportsensor/adapter/HistoryAdapter.java new file mode 100644 index 0000000..99e2246 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/adapter/HistoryAdapter.java @@ -0,0 +1,19 @@ +package com.handset.serialportsensor.adapter; + +import android.support.annotation.Nullable; +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.handset.serialportsensor.R; +import java.util.List; + +public class HistoryAdapter extends BaseQuickAdapter { + + public HistoryAdapter(@Nullable List data) { + super(R.layout.rv_item_history, data); + } + + @Override + protected void convert(BaseViewHolder helper, String item) { + helper.setText(R.id.item_history, item); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/adapter/LeftAdapter.java b/app/src/main/java/com/handset/serialportsensor/adapter/LeftAdapter.java new file mode 100644 index 0000000..056ac9d --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/adapter/LeftAdapter.java @@ -0,0 +1,86 @@ +package com.handset.serialportsensor.adapter; + +import android.text.TextUtils; + +import com.blankj.utilcode.util.SPUtils; +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.chad.library.adapter.base.entity.MultiItemEntity; +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.bean.LeftDetailBean; +import com.handset.serialportsensor.bean.LeftHeadBean; + +import java.util.List; + +public class LeftAdapter extends BaseMultiItemQuickAdapter { + + public static final int TYPE_HEAD = 1; + public static final int TYPE_DETAIL = 2; + + /** + * Same as QuickAdapter#QuickAdapter(Context,int) but with + * some initialization data. + * + * @param data A new list is created out of this one to avoid mutable list + */ + public LeftAdapter(List data) { + super(data); + + addItemType(TYPE_HEAD, R.layout.left_rv_item_head); + addItemType(TYPE_DETAIL, R.layout.left_rv_item_detail); + } + + @Override + protected void convert(BaseViewHolder helper, MultiItemEntity item) { + switch (helper.getItemViewType()) { + case TYPE_HEAD: + if (item instanceof LeftHeadBean) { + helper.setImageResource(R.id.left_rv_item_image, ((LeftHeadBean) item).getImageRes()) + .setText(R.id.left_rv_item_title, ((LeftHeadBean) item).getTitle()) + .setText(R.id.left_rv_item_value, + TextUtils.isEmpty(((LeftHeadBean) item).getValue()) ? "" + : ((LeftHeadBean) item).getValue()); + + helper.itemView.setOnClickListener(v -> { + collapseOrExpand(item); + }); + } + break; + case TYPE_DETAIL: + if (item instanceof LeftDetailBean) { + helper.setText(R.id.left_rv_item_item, ((LeftDetailBean) item).getItem()) + .setChecked(R.id.left_rv_item_check, ((LeftDetailBean) item).isCheck()); + + helper.itemView.setOnClickListener(v -> { + int parentPosition = getParentPosition(item); + LeftHeadBean headBean = (LeftHeadBean) getData().get(parentPosition); + + List subItems = headBean.getSubItems(); + for (int i = 0; i < subItems.size(); i++) { + if (subItems.get(i).isCheck()) { + subItems.get(i).setCheck(false); + break; + } + } + + int subPosition = helper.getAdapterPosition() - parentPosition - 1; + LeftDetailBean bean = subItems.get(subPosition); + bean.setCheck(true); + headBean.setValue(String.valueOf(bean.getItem())); + SPUtils.getInstance().put(headBean.getSpKey(), headBean.getValue()); + notifyDataSetChanged(); + }); + } + break; + } + } + + public void collapseOrExpand(MultiItemEntity item) { + int position = getParentPosition(item); + if (((LeftHeadBean) item).isExpanded()) { + collapse(position); + } else { + expand(position); + } + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/adapter/MsgAdapter.java b/app/src/main/java/com/handset/serialportsensor/adapter/MsgAdapter.java new file mode 100644 index 0000000..a835827 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/adapter/MsgAdapter.java @@ -0,0 +1,46 @@ +package com.handset.serialportsensor.adapter; + +import android.text.TextUtils; +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.bean.RawData; +import java.util.List; +import java.util.Locale; + + +public class MsgAdapter extends BaseMultiItemQuickAdapter { + + private String mFormat; + + /** + * Same as QuickAdapter#QuickAdapter(Context,int) but with + * some initialization data. + * + * @param data A new list is created out of this one to avoid mutable list + */ + public MsgAdapter(List data) { + super(data); + + addItemType(RawData.TYPE_RECEIVE, R.layout.rv_item_receive); + addItemType(RawData.TYPE_SEND, R.layout.rv_item_send); + } + + @Override + protected void convert(BaseViewHolder helper, RawData item) { + if (TextUtils.isEmpty(mFormat)) { + mFormat = mContext.getString(R.string.time_format); + } + if (item.getItemType() == RawData.TYPE_RECEIVE) { + helper.setGone(R.id.item_receive_date, !TextUtils.isEmpty(item.getDate())) + .setText(R.id.item_receive_date, TextUtils.isEmpty(item.getDate()) ? "" + : String.format(Locale.getDefault(), mFormat, item.getDate())) + .setText(R.id.item_receive_contain, item.getMessage()); + } else { + helper.setGone(R.id.item_send_date, !TextUtils.isEmpty(item.getDate())) + .setText(R.id.item_send_date, TextUtils.isEmpty(item.getDate()) ? "" + : String.format(Locale.getDefault(), mFormat, item.getDate())) + .setText(R.id.item_send_contain, item.getMessage()); + } + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/adapter/SettingsAdapter.java b/app/src/main/java/com/handset/serialportsensor/adapter/SettingsAdapter.java new file mode 100644 index 0000000..eb79b3c --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/adapter/SettingsAdapter.java @@ -0,0 +1,98 @@ +package com.handset.serialportsensor.adapter; + +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.bean.SettingsItem; +import com.handset.serialportsensor.constant.Constant; + +import java.util.List; + +public class SettingsAdapter extends RecyclerView.Adapter { + private List list; + private int role; + private OnItemClickListener listener; + + public void setOnItemClickListener(OnItemClickListener onItemClickListener) { + this.listener = onItemClickListener; + } + + public interface OnItemClickListener { + void onItemClick(View view, int position); + } + + public SettingsAdapter(List list, int role) { + this.list = list; + this.role = role; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + View inflate = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.settings_adapter_item, viewGroup, false); + return new ViewHolder(inflate); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder viewHolder, final int i) { + final SettingsItem item = list.get(i); + viewHolder.iv_img.setImageResource(item.getIconRes()); + viewHolder.tv_title.setText(item.getName()); + viewHolder.itemView.setOnClickListener((View view) -> + Toast.makeText(view.getContext(), item.getName(), Toast.LENGTH_SHORT).show() + ); + if (i == list.size() - 1) { + viewHolder.line.setVisibility(View.GONE); + if (role == Constant.SENIOR_ROLE) { + viewHolder.third_layout.setVisibility(View.VISIBLE); + } else { + viewHolder.third_layout.setVisibility(View.INVISIBLE); + } + } else { + viewHolder.third_layout.setVisibility(View.GONE); + viewHolder.line.setVisibility(View.VISIBLE); + } + + viewHolder.itemView.setOnClickListener((View view) -> listener.onItemClick(view, i)); + if (role == Constant.NOT_CONNECTED_ROLE) { + if (item.getPosition() == 0 || item.getPosition() == 2 || item.getPosition() == 7 || item.getPosition() == 9) { + viewHolder.iv_img.setImageResource(R.mipmap.ic_settings3_gray); + viewHolder.tv_title.setTextColor(viewHolder.tv_title.getContext().getResources().getColor(R.color.very_light_gray)); + viewHolder.iv_right.setImageResource(R.mipmap.ic_right_arrow_light); + viewHolder.itemView.setClickable(false); + } + } + } + + @Override + public int getItemCount() { + return list.size(); + } + + class ViewHolder extends RecyclerView.ViewHolder { + private ImageView iv_img; + private TextView tv_title; + private ImageView iv_right; + private View line; + private LinearLayout third_layout; + + public ViewHolder(@NonNull View itemView) { + super(itemView); + iv_img = itemView.findViewById(R.id.iv_img); + tv_title = itemView.findViewById(R.id.tv_title); + iv_right = itemView.findViewById(R.id.iv_right); + line = itemView.findViewById(R.id.line); + third_layout = itemView.findViewById(R.id.third_layout); + } + } +} + + diff --git a/app/src/main/java/com/handset/serialportsensor/bean/LeftDetailBean.java b/app/src/main/java/com/handset/serialportsensor/bean/LeftDetailBean.java new file mode 100644 index 0000000..629c3e6 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/bean/LeftDetailBean.java @@ -0,0 +1,31 @@ +package com.handset.serialportsensor.bean; + +import com.chad.library.adapter.base.entity.MultiItemEntity; +import com.handset.serialportsensor.adapter.LeftAdapter; + +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +public class LeftDetailBean implements MultiItemEntity { + private String item; + + private boolean isCheck; + + public LeftDetailBean(String item) { + this.item = item; + } + + public LeftDetailBean(String item, boolean isCheck) { + this.item = item; + this.isCheck = isCheck; + } + + @Override + public int getItemType() { + return LeftAdapter.TYPE_DETAIL; + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/bean/LeftHeadBean.java b/app/src/main/java/com/handset/serialportsensor/bean/LeftHeadBean.java new file mode 100644 index 0000000..33d14d5 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/bean/LeftHeadBean.java @@ -0,0 +1,36 @@ +package com.handset.serialportsensor.bean; + +import android.support.annotation.DrawableRes; + +import com.chad.library.adapter.base.entity.AbstractExpandableItem; +import com.chad.library.adapter.base.entity.MultiItemEntity; +import com.handset.serialportsensor.adapter.LeftAdapter; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@EqualsAndHashCode(callSuper = true) +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class LeftHeadBean extends AbstractExpandableItem implements MultiItemEntity { + @DrawableRes + private int imageRes; + private String title; + private String value; + private String spKey; + + @Override + public int getLevel() { + return 0; + } + + @Override + public int getItemType() { + return LeftAdapter.TYPE_HEAD; + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/bean/MetaData.java b/app/src/main/java/com/handset/serialportsensor/bean/MetaData.java new file mode 100644 index 0000000..65c4143 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/bean/MetaData.java @@ -0,0 +1,187 @@ +package com.handset.serialportsensor.bean; + +import android.util.Log; + +import com.handset.serialportlib.ByteUtils; +import com.handset.serialportsensor.constant.Constant; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MetaData { + private static final String logTag = "HANDSET-JE002-EX"; + + private static final BigDecimal T_CEILING = new BigDecimal(100.00f); + private static final BigDecimal T_FLOOR = new BigDecimal(-60.00f); + private static final BigDecimal H_CEILING = new BigDecimal(100.00f); + private static final BigDecimal H_FLOOR = new BigDecimal(00.00f); + private static final BigDecimal I_CEILING = new BigDecimal(300.00f); + private static final BigDecimal I_FLOOR = new BigDecimal(00.00f); + private static final BigDecimal O_CEILING = new BigDecimal(300.00f); + private static final BigDecimal O_FLOOR = new BigDecimal(00.00f); + private static final BigDecimal DP_CEILING = new BigDecimal(600.00f); + private static final BigDecimal DP_FLOOR = new BigDecimal(-600.00f); + private static final BigDecimal P20_CEILING = new BigDecimal(300.00f); + private static final BigDecimal P20_FLOOR = new BigDecimal(00.00f); + private static final BigDecimal H20_CEILING = new BigDecimal(100.00f); + private static final BigDecimal H20_FLOOR = new BigDecimal(00.00f); + + private static final int[] temperatureConvertDatum = { + 18, 23, 28, 34, 41, 50, 61, 73, 88, 105, + 125, 148, 175, 207, 244, 286, 334, 390, 454, 528, + 611, 706, 814, 935, 1073, 1228, 1403, 1599, 1819, 2065, + 2339, 2645, 2985, 3362, 3781, 4244, 4756, 5321, 5942, 6626, + 7377, 8201, 9103, 10089, 11165, 12339, 13618, 15009, 16520, 18160, 19937 + }; + + private Integer makerId; + private String sensorNo; + private String sensorNoRadix; + private String eggNo; + private String eggType; + private String coneNo; + private String coneUsedTimes; + private Float temperature; + private Float humidity; + private Float innerPressure; + private Float outerPressure; + private Float diffPressure; + private Float degree20Pressure; + private Float degree20Humidity; + + public void doCalcMeta(String data) { + byte[] bytes = ByteUtils.hexStrToBytes(data.substring(0, data.length() - 4)); + switch (bytes[7] & 0xff) { + case Constant.Command.COMMAND_29: + this.setTemperature((float) parseValue(bytes) / 100); + break; + case Constant.Command.COMMAND_2A: + this.setInnerPressure((float) parseValue(bytes) / 1000); + break; + case Constant.Command.COMMAND_2B: + this.setHumidity((float) parseValue(bytes) / 100); + break; + case Constant.Command.COMMAND_2C: + this.setOuterPressure((float) parseValue(bytes) / 1000); + break; + case Constant.Command.COMMAND_2D: + this.setDiffPressure((float) parseValue(bytes) / 1000); + break; + case Constant.Command.COMMAND_2E: + this.setDegree20Humidity((float) parseValue(bytes) / 100); + break; + case Constant.Command.COMMAND_2F: + this.setDegree20Pressure((float) parseValue(bytes) / 1000); + break; + default: + break; + } + } + + public void doCalcMetaEx() { + calcPressDiff(); + calcPressOfDegree20(); + calcHumidityOfDegree20(); + } + public void calcPressDiff() { + try { + if(this.diffPressure == 0) { + Log.i(logTag, "Diff pressure not report, need to be calculated"); + this.diffPressure = this.innerPressure - this.outerPressure; + } + } catch (Exception e) { + e.printStackTrace(); + this.diffPressure = 0.00f; + } + } + + public void calcPressOfDegree20() { + try { + if(this.degree20Pressure == 0) { + Log.i(logTag, "20 degree pressure not report, need to be calculated"); + int tempMustInt = (int) (this.temperature * 10); + double temp = (293000.00) / ((tempMustInt + 400) + 2330); + double innerPress20Degree = (temp * (this.innerPressure * 1000)) / 100 / 1000; + + DecimalFormat df = new DecimalFormat(Constant.FORMAT_FLOAT_PATTERN); + df.setRoundingMode(RoundingMode.FLOOR); + this.degree20Pressure = Float.valueOf(df.format(innerPress20Degree)); + } + } catch (Exception e) { + e.printStackTrace(); + this.degree20Pressure = 0.00f; + } + } + + public void calcHumidityOfDegree20() { + try { + if(this.degree20Humidity == 0) { + Log.i(logTag, "20 degree humidity not report, need to be calculated"); + int tmp = (((int) (this.temperature * 10) + 400) / 10) / 2; + tmp = (((int) (this.temperature * 10) + 400) / 10) % 2 == 0 ? tmp : tmp + 1; + tmp = tmp > 50 || tmp < 0 ? 50 : tmp; + + double degree20Humidity = (temperatureConvertDatum[tmp] * ((double) (this.humidity * 100) / 100)) / 2339; + DecimalFormat df2 = new DecimalFormat(Constant.FORMAT_FLOAT_PATTERN); + df2.setRoundingMode(RoundingMode.FLOOR); + this.degree20Humidity = Float.valueOf(df2.format(degree20Humidity)); + } + } catch (Exception e) { + e.printStackTrace(); + this.degree20Humidity = 0.00f; + } + + this.degree20Humidity = new BigDecimal(this.degree20Humidity).compareTo(H20_CEILING) >=0 ? 100.f : this.degree20Humidity; + } + + private int parseValue(byte[] bytes) { + return (bytes[9] & 0xff) | ((bytes[10] & 0xff) << 8) | ((bytes[11] & 0xff) << 16) | ((bytes[12] & 0xff) << 24); + } + + public boolean isValid() { + BigDecimal t = new BigDecimal(this.temperature); + BigDecimal h = new BigDecimal(this.humidity); + BigDecimal i = new BigDecimal(this.innerPressure); + BigDecimal o = new BigDecimal(this.outerPressure); + BigDecimal dp = new BigDecimal(this.diffPressure); + BigDecimal p20 = new BigDecimal(this.degree20Pressure); + BigDecimal h20 = new BigDecimal(this.degree20Humidity); + Log.i(logTag, "t:" + t.floatValue() + ",h:" + h.floatValue() + ",i:" + i.floatValue() + ",o:" + o.floatValue() + ",dp:" + dp.floatValue() + ",p20:" + p20.floatValue()+ ",h20:" + h20.floatValue()); + return t.compareTo(T_CEILING) <= 0 && t.compareTo(T_FLOOR) >= 0 + && h.compareTo(H_CEILING) <= 0 && h.compareTo(H_FLOOR) >= 0 + && i.compareTo(I_CEILING) <= 0 && i.compareTo(I_FLOOR) >= 0 + && o.compareTo(O_CEILING) <= 0 && o.compareTo(O_FLOOR) >= 0 + && dp.compareTo(DP_CEILING) <= 0 && dp.compareTo(DP_FLOOR) >= 0 + && p20.compareTo(P20_CEILING) <= 0 && p20.compareTo(P20_FLOOR) >= 0 + && h20.compareTo(H20_CEILING) <= 0 && h20.compareTo(H20_FLOOR) >= 0 + ; + } + + public void resetData() { + this.setSensorNo(null); + this.setSensorNoRadix(null); + this.temperature = 0.0F; + this.humidity = 0.0F; + this.innerPressure = 0.0F; + this.outerPressure = 0.0F; + this.diffPressure = 0.0F; + this.degree20Humidity = 0.0F; + this.degree20Pressure = 0.0F; + } + + public void resetData20Degree() { + this.diffPressure = 0.0F; + this.degree20Humidity = 0.0F; + this.degree20Pressure = 0.0F; + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/bean/RawData.java b/app/src/main/java/com/handset/serialportsensor/bean/RawData.java new file mode 100644 index 0000000..2902cc4 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/bean/RawData.java @@ -0,0 +1,34 @@ +package com.handset.serialportsensor.bean; + +import com.chad.library.adapter.base.entity.MultiItemEntity; + +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +public class RawData implements MultiItemEntity { + public static final int TYPE_RECEIVE = 0; + public static final int TYPE_SEND = 1; + + private int mItemType; + private String date; + private String message; + + public RawData(int itemType) { + mItemType = itemType; + } + + public RawData(int itemType, String date, String message) { + mItemType = itemType; + this.date = date; + this.message = message; + } + + @Override + public int getItemType() { + return mItemType; + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/bean/Sensor.java b/app/src/main/java/com/handset/serialportsensor/bean/Sensor.java new file mode 100644 index 0000000..d62230f --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/bean/Sensor.java @@ -0,0 +1,29 @@ +package com.handset.serialportsensor.bean; + +import org.kymjs.kjframe.database.annotate.Id; +import org.kymjs.kjframe.database.annotate.Table; +import org.kymjs.kjframe.database.annotate.Transient; + +/** + * Created by zy on 2019/2/24. + * 用来记录传感器信息 + */ + +@Table(name = "sensor") +public class Sensor { + + @Id + public int id; + /*传感器编号*/ + public long sensor_id; + /*弹号*/ + public String egg_id; + /*弹型*/ + public String egg_type; + /*筒号*/ + public String tupe_id; + public String tv_tupe_use_times; + + @Transient + public int tagBackup = 0; +} diff --git a/app/src/main/java/com/handset/serialportsensor/bean/SettingsItem.java b/app/src/main/java/com/handset/serialportsensor/bean/SettingsItem.java new file mode 100644 index 0000000..493d7fd --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/bean/SettingsItem.java @@ -0,0 +1,37 @@ +package com.handset.serialportsensor.bean; + +public class SettingsItem { + private String name; + private int iconRes; + private int position; + + public SettingsItem(String name, int iconRes, int position) { + this.name = name; + this.iconRes = iconRes; + this.position = position; + } + + public int getPosition() { + return position; + } + + public void setPosition(int position) { + this.position = position; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getIconRes() { + return iconRes; + } + + public void setIconRes(int iconRes) { + this.iconRes = iconRes; + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/bean/TestData.java b/app/src/main/java/com/handset/serialportsensor/bean/TestData.java new file mode 100644 index 0000000..2d2162c --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/bean/TestData.java @@ -0,0 +1,80 @@ +package com.handset.serialportsensor.bean; + +public class TestData { + + private String title; + + public String getZhankai() { + return zhankai; + } + + public void setZhankai(String zhankai) { + this.zhankai = zhankai; + } + + private String zhankai; + private int tag; + public boolean isSelect; + public int temp; + public int neiYa; + public int waiYa; + public int shiDu; + + public int getTemp() { + return temp; + } + + public void setTemp(int temp) { + this.temp = temp; + } + + public int getNeiYa() { + return neiYa; + } + + public void setNeiYa(int neiYa) { + this.neiYa = neiYa; + } + + public int getWaiYa() { + return waiYa; + } + + public void setWaiYa(int waiYa) { + this.waiYa = waiYa; + } + + public int getShiDu() { + return shiDu; + } + + public void setShiDu(int shiDu) { + this.shiDu = shiDu; + } + + public boolean isSelect() { + return isSelect; + } + + public void setSelect(boolean isSelect) { + this.isSelect = isSelect; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getTag() { + return tag; + } + + public void setTag(int tag) { + this.tag = tag; + } + + +} diff --git a/app/src/main/java/com/handset/serialportsensor/bean/TestRecordsTotal.java b/app/src/main/java/com/handset/serialportsensor/bean/TestRecordsTotal.java new file mode 100644 index 0000000..89b6103 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/bean/TestRecordsTotal.java @@ -0,0 +1,49 @@ +package com.handset.serialportsensor.bean; + +import org.kymjs.kjframe.database.annotate.Id; +import org.kymjs.kjframe.database.annotate.Property; +import org.kymjs.kjframe.database.annotate.Table; + +/** + * Created by zy on 2019/2/24. + * 单条汇总测试数据,求取平均值之后的数据 + */ + +@Table(name = "test_record_total") +public class TestRecordsTotal { + /** + * 测试id + */ + @Id + public long id; + + //记录数据保存的日期标记,方便之后能够查出来 + public long day_t; + + /*温度*/ + public float temp; + /*湿度*/ + public float Hum; + /*内压*/ + public float pressurein; + + /*湿度*/ + public float Hum20; + /*内压*/ + public float pressurein20; + /*外压*/ + public float pressureout; + /*压差*/ + public float pressure_yacha; + /*传感器编号*/ + public long sensor_id; + /*波特率*/ + @Property(column = "tupe_id") + public String botelv; + /*筒使用次数*/ + public String tupe_use_times; + /*测试结束时间*/ + public long end_time; + /*数据是否已经备份过*/ + public int tagBackup = 0; +} diff --git a/app/src/main/java/com/handset/serialportsensor/bean/TestRecordsitems.java b/app/src/main/java/com/handset/serialportsensor/bean/TestRecordsitems.java new file mode 100644 index 0000000..41b16b3 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/bean/TestRecordsitems.java @@ -0,0 +1,28 @@ +package com.handset.serialportsensor.bean; + +import org.kymjs.kjframe.database.annotate.Id; +import org.kymjs.kjframe.database.annotate.Table; + +/** + * Created by zy on 2019/2/24. + */ +@Table(name = "test_record_item") +public class TestRecordsitems { + @Id(autoInc = true) + public int id; + /** + * 对应 TestRecordsTotal 中的id + */ + public long test_id; + + /** + * 对应数据类型 + * 具体类型,见报文解析字段 + */ + public int type; + + /** + * 测试的数据值 + */ + public float value; +} diff --git a/app/src/main/java/com/handset/serialportsensor/bean/ThresholdBean.java b/app/src/main/java/com/handset/serialportsensor/bean/ThresholdBean.java new file mode 100644 index 0000000..397b53f --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/bean/ThresholdBean.java @@ -0,0 +1,23 @@ +package com.handset.serialportsensor.bean; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ThresholdBean { + public String temperatureFloor; + public String temperatureCeiling; + public String humidityFloor; + public String humidityCeiling; + public String innerPressureFloor; + public String innerPressureCeiling; + public String outerPressureFloor; + public String outerPressureCeiling; + public String diffPressureFloor; + public String diffPressureCeiling; +} diff --git a/app/src/main/java/com/handset/serialportsensor/constant/Constant.java b/app/src/main/java/com/handset/serialportsensor/constant/Constant.java new file mode 100644 index 0000000..28686b2 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/constant/Constant.java @@ -0,0 +1,74 @@ +package com.handset.serialportsensor.constant; + +import android.graphics.Color; + +public class Constant { + public final static String SENSOR_ID = "sensor_id"; + public final static String BAUD_RATE = "baud_rate"; + public static final String ROLE_KEY = "role_key"; + public static final int NOT_CONNECTED_ROLE = 0; + public static final int PRIMARY_ROLE = 1; + public static final int SENIOR_ROLE = 2; + + public static final int BAUD_9600 = 9600; + public static final int BAUD_19200 = 19200; + public static final int BAUD_38400 = 38400; + + public static final String DDDD = "DDDD"; + + //ID高16位 + public static final String ID_HIGH_KEY = "id_high_key"; + //ID低16位 + public static final String ID_LOW_KEY = "id_low_key"; + public static final String THRESHOLD_KEY = "id_key"; + public static final String idHigh1 = "id1"; + public static final String idHigh2 = "id2"; + public static final String idHigh3 = "id3"; + public static final String idHigh4 = "id4"; + + public static final int READ_TIME_OUT = 3000; + public static final int READ_TIME_OUT_TIME = 1000;//延迟1秒 + + public static final String FORMAT_FLOAT_PATTERN = "0.00"; + + public final static int red = Color.rgb((255), (0), (0)); + public final static int green = Color.rgb((0), (255), (0)); + public final static int yellow = Color.rgb((255), (255), (0)); + public final static int grey = Color.rgb((0x9d), (0x9d), (0x9d)); + + public static final class Command { + public static final int COMMAND_25 = 0x25;//ID查询 + public static final int COMMAND_26 = 0x26;//ID上报 + public static final int COMMAND_27 = 0x27;//检测仪模式切换 + public static final int COMMAND_28 = 0x28;//模式切换结果指令上报 + public static final int COMMAND_29 = 0x29;//温度指令上报 + public static final int COMMAND_2A = 0x2A;//内压指令上报 + public static final int COMMAND_2B = 0x2B;//湿度指令上报 + public static final int COMMAND_2C = 0x2C;//外压指令上报 + public static final int COMMAND_2D = 0x2D;//差压指令上报 + public static final int COMMAND_2E = 0x2E;//20度湿度指令上报 + public static final int COMMAND_2F = 0x2F;//20度内压指令上报 + public static final int COMMAND_30 = 0x30;//弹号读取 + public static final int COMMAND_31 = 0x31;//弹号指令上报 + public static final int COMMAND_32 = 0x32;//弹号设置 + public static final int COMMAND_33 = 0x33;//弹号设置指令上报 + public static final int COMMAND_34 = 0x34;//筒号读取 + public static final int COMMAND_35 = 0x35;//筒号指令上报 + public static final int COMMAND_36 = 0x36;//筒号设置 + public static final int COMMAND_37 = 0x37;//筒号设置指令上报 + public static final int COMMAND_38 = 0x38;//弹筒使用次数读取 + public static final int COMMAND_39 = 0x39;//弹筒使用次数指令上报 + public static final int COMMAND_3A = 0x3A;//弹筒使用次数设置 + public static final int COMMAND_3B = 0x3B;//弹筒使用次数设置指令上报 + public static final int COMMAND_3C = 0x3C;//波特率设置 + public static final int COMMAND_3D = 0x3D;//波特率设置结果指令上报 + public static final int COMMAND_3E = 0x3E; //弹型读取 + public static final int COMMAND_3F = 0x3F; //弹型读取回复 + public static final int COMMAND_40 = 0x40; //弹型设置 + public static final int COMMAND_41 = 0x41; //弹型设置回复 + public static final int COMMAND_49 = 0x49;//恢复出厂设置 + public static final int COMMAND_4A = 0x4A;//恢复出厂设置结果返回 + public static final int COMMAND_50 = 0x50;//传感器ID设置 + public static final int COMMAND_51 = 0x51;//传感器ID设置 + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/db/DBUpdateHelperMY.java b/app/src/main/java/com/handset/serialportsensor/db/DBUpdateHelperMY.java new file mode 100644 index 0000000..336d226 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/db/DBUpdateHelperMY.java @@ -0,0 +1,55 @@ +package com.handset.serialportsensor.db; + +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; + +import org.kymjs.kjframe.KJDB; + +/** + * Created by zy on 2019/3/7. + */ + + +public class DBUpdateHelperMY implements KJDB.DbUpdateListener { + private static final String TAG = com.suntiago.dblib.DBUpdateHelper.class.getSimpleName(); + public static final int DATABASE_VERSION = 2; + + public DBUpdateHelperMY() { + } + + public void onCreate(Context context, SQLiteDatabase sqLiteDatabase) { + } + + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + if (oldVersion < 2) { + if (tabbleIsExist(db, "sensor")) { + db.execSQL("ALTER TABLE media ADD COLUMN tv_tupe_use_times String DEFAULT \'\';"); + } + } + } + + + public boolean tabbleIsExist(SQLiteDatabase db, String tableName) { + boolean result = false; + if (tableName == null) { + return false; + } + Cursor cursor = null; + try { + //这里表名可以是Sqlite_master + String sql = "select count(*) as c from htjc_sensor_history where type ='table' and name ='" + tableName + "'"; + cursor = db.rawQuery(sql, null); + if (cursor.moveToNext()) { + int count = cursor.getInt(0); + if (count > 0) { + result = true; + } + } + + } catch (Exception e) { + // TODO: handle exception + } + return result; + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/presenter/SurfaceContract.java b/app/src/main/java/com/handset/serialportsensor/presenter/SurfaceContract.java new file mode 100644 index 0000000..3007cdf --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/presenter/SurfaceContract.java @@ -0,0 +1,15 @@ +package com.handset.serialportsensor.presenter; + +import com.handset.serialportsensor.bean.RawData; + +public interface SurfaceContract { + interface ISerialView { + void onSerialOpen(boolean isOpen); + + void onSerialData(RawData rawData); + + void onSerialBaudRate(Integer baudRate); + + void onSerialError(Integer errorCode); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/presenter/SurfacePresenter.java b/app/src/main/java/com/handset/serialportsensor/presenter/SurfacePresenter.java new file mode 100644 index 0000000..49dac60 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/presenter/SurfacePresenter.java @@ -0,0 +1,315 @@ +package com.handset.serialportsensor.presenter; + +import android.os.SystemClock; +import android.text.TextUtils; +import android.util.Log; + +import com.blankj.utilcode.util.SPUtils; +import com.blankj.utilcode.util.ToastUtils; +import com.handset.serialportlib.CRCUtils; +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.activity.SPKey; +import com.handset.serialportsensor.bean.RawData; +import com.handset.serialportlib.ByteUtils; +import com.handset.serialportlib.SerialPort; +import com.handset.serialportsensor.utils.SplitUtils; + +import io.reactivex.BackpressureStrategy; +import io.reactivex.Flowable; +import io.reactivex.FlowableOnSubscribe; +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.LinkedHashSet; + +import org.joda.time.DateTime; + +public class SurfacePresenter { + private static final String logTag = "HANDSET-JE002-EX"; + + private final static String POWER_EN_PATH = "/sys/class/peijian_dev/function/PeijianPowerEn"; + private final static String POGO_WAKE = "/sys/class/peijian_dev/function/pogo_wake"; + + private final static String SERIAL_PATH = "dev/ttyHSL1"; + private final static Integer SERIAL_BAUD_RATE = 38400; + private final static String mDateFormat = "HH:mm:ss:SSS"; + private SurfaceContract.ISerialView mSerialView; + + private LinkedHashSet mSendHistory; + + private int mCheckDigit; + private int mDataBits; + private int mStopBit; + + private boolean isHexReceive; + private boolean isHexSend; + private boolean isShowSend; + private boolean isShowTime; + + private SerialPort mSerialPort; + private boolean isInterrupted; + private Disposable mReceiveDisposable; + private ObservableEmitter mEmitter; + private Disposable mSendDisposable; + + public SurfacePresenter(SurfaceContract.ISerialView view) { + mSerialView = view; + isHexReceive = true; + isHexSend = SPUtils.getInstance().getBoolean(SPKey.SETTING_SEND_TYPE, (true)); + isShowSend = SPUtils.getInstance().getBoolean(SPKey.SETTING_RECEIVE_SHOW_SEND, (true)); + isShowTime = SPUtils.getInstance().getBoolean(SPKey.SETTING_RECEIVE_SHOW_TIME, (true)); + + try { + mSendHistory = (LinkedHashSet) SPUtils.getInstance().getStringSet(SPKey.SEND_HISTORY, new LinkedHashSet<>((30))); + } catch (ClassCastException e) { + e.printStackTrace(); + mSendHistory = new LinkedHashSet<>((30)); + } + } + + private void refreshValueFormSp() { + //String mPath = SPUtils.getInstance().getString(SPKey.SERIAL_PORT, ("")); + //int mBaudRate = Integer.parseInt(SPUtils.getInstance().getString(SPKey.BAUD_RATE, ("9600"))); + mCheckDigit = Integer.parseInt(SPUtils.getInstance().getString(SPKey.CHECK_DIGIT, ("0"))); + mDataBits = Integer.parseInt(SPUtils.getInstance().getString(SPKey.DATA_BITS, ("8"))); + mStopBit = Integer.parseInt(SPUtils.getInstance().getString(SPKey.STOP_BIT, ("1"))); + } + + public void open() { + refreshValueFormSp(); + try { + mSerialPort = new SerialPort(new File(SERIAL_PATH), SERIAL_BAUD_RATE, mCheckDigit, mDataBits, mStopBit, (0)); + } catch (Exception e) { + e.printStackTrace(); + mSerialPort = null; + ToastUtils.showLong(R.string.open_serial_port_failure); + } + + if (mSerialPort != null) { + this.initBLNStatus('1'); + isInterrupted = false; + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + onReceiveSubscribe(); + onSendSubscribe(); + mSerialView.onSerialOpen((mSerialPort != null)); + //ToastUtils.showLong(R.string.open_serial_port_success); + } else { + mSerialView.onSerialError((0)); + } + } + + public void open(Integer baudRate) { + if (baudRate == null) { + Log.i(logTag, ("onSerialBaudRate null")); + return; + } + + refreshValueFormSp(); + try { + Log.i(logTag, ("onSerialBaudRate: " + baudRate)); + mSerialPort = new SerialPort(new File(SERIAL_PATH), baudRate, mCheckDigit, mDataBits, mStopBit, (0)); + } catch (IOException e) { + e.printStackTrace(); + ToastUtils.showLong(R.string.open_serial_port_failure); + } + + if (mSerialPort != null) { + this.initBLNStatus('1'); + isInterrupted = false; + + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + onReceiveSubscribe(); + onSendSubscribe(); + } + + mSerialView.onSerialOpen((mSerialPort != null)); + } + + public void close() { + Log.i(logTag, ("closing!!!")); + this.initBLNStatus('0'); + isInterrupted = true; + + disposable(mReceiveDisposable); + disposable(mSendDisposable); + mEmitter = null; + mSerialPort = null; + + mSerialView.onSerialOpen((false)); + } + + public void initBLNStatus(char status) { + setBLNStatus(status, POWER_EN_PATH); + setBLNStatus(status, POGO_WAKE); + } + + private void setBLNStatus(char status, String path) { + FileOutputStream fos = null; + try { + File file = new File(path); + if (file.exists()) { + fos = new FileOutputStream(file); + fos.write(status); + fos.flush(); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + private void onSendSubscribe() { + mSendDisposable = + Observable.create((ObservableOnSubscribe) emitter -> mEmitter = emitter) + .filter(s -> !TextUtils.isEmpty(s)) + .doOnNext(s -> mSendHistory.add(s)) + .doOnNext(s -> { + Log.i(logTag, ("Sent: " + addSpace(s.toUpperCase()))); + mSerialPort.getOutputStream().write(isHexSend ? ByteUtils.hexStrToBytes(s) : ByteUtils.strToAsciiBytes(s)); + mSerialPort.getOutputStream().flush(); + }) + .observeOn(AndroidSchedulers.mainThread()) + .filter(s -> isShowSend) + .subscribe(s -> { + //Log.d(logTag, ("sender: " + addSpace(s.toUpperCase()))); + mSerialView.onSerialData(new RawData(RawData.TYPE_SEND, isShowTime ? DateTime.now().toString(mDateFormat) : "", addSpace(s.toUpperCase()))); + }, Throwable::printStackTrace); + } + + private void onReceiveSubscribe() { + mReceiveDisposable = + Flowable.create((FlowableOnSubscribe) emitter -> { + int first, available; + InputStream is = mSerialPort.getInputStream(); + while (!isInterrupted + && mSerialPort != null + && is != null + && (first = is.read()) != -1) { + do { + available = is.available(); + SystemClock.sleep((1)); + } while (available != is.available()); + + available = is.available(); + byte[] bytes = new byte[available + 1]; + int n = is.read(bytes, (1), available); + Log.d(logTag, ("Received n: " + n + ", raw: " + ByteUtils.bytesToHexStr(bytes))); + bytes[0] = (byte) (first & 0xFF); + Log.d(logTag, ("Received first: " + first + ", raw: " + ByteUtils.bytesToHexStr(bytes))); + emitter.onNext(bytes); + } + Log.d(logTag, ("onReceiveSubscribe close:")); + close(); + }, BackpressureStrategy.MISSING + ).retry().map(bytes -> isHexReceive ? ByteUtils.bytesToHexStr(bytes) : ByteUtils.bytesToAscii(bytes)) + .filter(this::validate) + .filter(this::crcVerify) + .map(this::getBody) + .subscribeOn(Schedulers.single()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + it -> { + Log.v(logTag, ("Received: " + addSpace(it))); + mSerialView.onSerialData(new RawData(RawData.TYPE_RECEIVE, isShowTime ? DateTime.now().toString(mDateFormat) : "", it)); + }, Throwable::printStackTrace + ); + } + + private boolean validate(String raw) { + try { + Log.v(logTag, ("len: " + raw.length())); + return !TextUtils.isEmpty(raw) && raw.length() >= 22; + } catch (Exception e) { + Log.v(logTag, ("validate, exp: " + e.getMessage())); + return false; + } + } + + private boolean crcVerify(String rawData) { + try { + Log.v(logTag, ("crcVerify: " + rawData)); + for (String str : SplitUtils.split(rawData)) { + if (TextUtils.isEmpty(str) || str.length() < 4) continue; + if (!CRCUtils.genCrc(str.substring(4, str.length() - 4)).equals(str.substring(str.length() - 4))) { + Log.w(logTag, ("str: " + str + " crc fail!")); + return (str.charAt(12) == '0' && str.charAt(13) == '0' && str.charAt(14) == '2' && str.charAt(15) == '6'); + } + } + return true; + } catch (Exception e) { + Log.v(logTag, ("crcVerify, exp: " + e.getMessage())); + return false; + } + } + + private String getBody(String raw) { + return raw; + } + + private String addSpace(String s) { + if (s.length() % 2 == 0) { + StringBuilder builder = new StringBuilder(); + char[] array = s.toCharArray(); + int length = array.length; + for (int i = 0; i < length; i += 2) { + if (i != 0 && i <= length - 2) { + builder.append(" "); + } + + builder.append(array[i]); + builder.append(array[i + 1]); + } + + return builder.toString(); + } + return s; + } + + public void write(String message) { + if (mEmitter == null) { + ToastUtils.showLong(R.string.open_serial_port_first); + return; + } + + if (TextUtils.isEmpty(message)) { + Log.w(logTag, "Message is empty!"); + return; + } + mEmitter.onNext(message); + } + + public void onDestroy() { + close(); + SPUtils.getInstance().put(SPKey.SEND_HISTORY, mSendHistory); + } + + private void disposable(Disposable disposable) { + if (disposable != null && !disposable.isDisposed()) { + disposable.dispose(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/handset/serialportsensor/utils/CRC16Utils.java b/app/src/main/java/com/handset/serialportsensor/utils/CRC16Utils.java new file mode 100644 index 0000000..2f4a791 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/CRC16Utils.java @@ -0,0 +1,78 @@ +package com.handset.serialportsensor.utils; + +/** + * @author dizhou + */ +public class CRC16Utils { + /* + * CCITT标准CRC16(1021)余数表 CRC16-CCITT ISO HDLC, ITU X.25, x16+x12+x5+1 多项式 + * 高位在先时生成多项式 Gm=0x11021 低位在先时生成多项式,Gm=0x8408 本例采用高位在先 + */ + private static int crc16_ccitt_table[] = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, + 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, + 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, + 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, + 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, + 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, + 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, + 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, + 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, + 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, + 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, + 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, + 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, + 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, + 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, + 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, + 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; + + public static int getCRC1021(byte bytes[]) { + return getCRC2(bytes); + } + + public static int getCRC1021_old(byte bytes[]) { + int crc = 0x00; // initial value + int polynomial = 0x1021; + for (int index = 0; index < bytes.length; index++) { + byte b = bytes[index]; + for (int i = 0; i < 8; i++) { + boolean bit = ((b >> (7 - i) & 1) == 1); + boolean c15 = ((crc >> 15 & 1) == 1); + crc <<= 1; + if (c15 ^ bit) crc ^= polynomial; + } + } + crc &= 0xffff; + return crc; + } + + public static int getCRC2(byte[] bytes) { + int CRC = 0xffff; + int POLYNOMIAL = 0xA001; + + int i, j; + for (i = 0; i < bytes.length; i++) { + CRC ^= ((int) bytes[i] & 0x00ff); + for (j = 0; j < 8; j++) { + if ((CRC & 0x0001) != 0) { + CRC >>= 1; + CRC ^= POLYNOMIAL; + } else { + CRC >>= 1; + } + } + } + return CRC ; + } + + // 测试 +// public static void main(String[] args) { +// // 0xf360 DD DD 13 01 03 EF 00 29 04 DB 08 00 00 1B 42 +// byte[] a = new byte[]{(byte) 0x13, (byte) 0x01, (byte) 0x03 +// , (byte) 0xef +// , (byte) 0x00, (byte) 0x29, (byte) 0x04, (byte) 0xdb, (byte) 0x08, (byte) 0x00, (byte) 0x00}; +// int crc2 = getCRC1021(a); +// System.out.println("结果=" + Integer.toHexString(crc2)); +// +// } +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/CrashHandler.java b/app/src/main/java/com/handset/serialportsensor/utils/CrashHandler.java new file mode 100644 index 0000000..8440ea8 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/CrashHandler.java @@ -0,0 +1,245 @@ +package com.handset.serialportsensor.utils; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Build; +import android.os.Environment; +import android.os.Looper; +import android.text.TextUtils; +import android.util.Log; +import android.widget.Toast; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.Thread.UncaughtExceptionHandler; +import java.lang.reflect.Field; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** + * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告. + * + * @author Jeremy + */ +public class CrashHandler implements UncaughtExceptionHandler { + public static final String TAG = "HANDSET-JE002-EX"; + private static final String BROADCAST_ACTION = "com.ss.permission.crash_log_update"; + //private LocalBroadcastManager mLocalBroadcastManager; + + //系统默认的UncaughtException处理类 + private UncaughtExceptionHandler mDefaultHandler; + + //程序的Context对象 + private Context mContext; + //用来存储设备信息和异常信息 + private Map infos = new HashMap<>(); + + //用于格式化日期,作为日志文件名的一部分 + private DateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss", Locale.CHINA); + + private String packageName = ""; + + private static class CrashHandlerHolder { + private static CrashHandler instance = new CrashHandler(); + } + + /** + * 保证只有一个CrashHandler实例 + */ + private CrashHandler() { + } + + /** + * 获取CrashHandler实例 ,单例模式 + */ + public static CrashHandler getInstance() { + return CrashHandlerHolder.instance; + } + + private String getCrashLogPath() { + return getSavePath(); + } + + private static String getSavePath() { + return Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + "htjc" + File.separator + "sensor" + File.separator + "crashlog/"; + } + + /** + * 初始化 + * use init(Context context) instead + * + * @param context context + */ + @Deprecated + public void init(Context context, String com, String pkgId) { + mContext = context; + //获取系统默认的UncaughtException处理器 + mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); + //mLocalBroadcastManager = LocalBroadcastManager.getInstance(mContext); + //设置该CrashHandler为程序的默认处理器 + Thread.setDefaultUncaughtExceptionHandler(this); + if (!TextUtils.isEmpty(pkgId)) { + this.packageName = pkgId; + } + } + + public void init(Context context) { + mContext = context; + //获取系统默认的UncaughtException处理器 + mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); + //mLocalBroadcastManager = LocalBroadcastManager.getInstance(mContext); + //设置该CrashHandler为程序的默认处理器 + Thread.setDefaultUncaughtExceptionHandler(this); + String pkgId = context.getPackageName().replace(".", "_") + "_"; + if (!TextUtils.isEmpty(pkgId)) { + this.packageName = pkgId; + } + + } + + /** + * 当UncaughtException发生时会转入该函数来处理 + */ + @Override + public void uncaughtException(Thread thread, Throwable ex) { + if (!handleException(ex) && mDefaultHandler != null) { + //如果用户没有处理则让系统默认的异常处理器来处理 + mDefaultHandler.uncaughtException(thread, ex); + } else { + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + Log.e(TAG, "error : ", e); + } + //退出程序 + android.os.Process.killProcess(android.os.Process.myPid()); + System.exit(1); + } + } + + /** + * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. + * + * @param ex 异常 + * @return true:如果处理了该异常信息;否则返回false. + */ + private boolean handleException(Throwable ex) { + if (ex == null) { + return false; + } + //使用Toast来显示异常信息 + new Thread() { + @Override + public void run() { + Looper.prepare(); + Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG).show(); + Looper.loop(); + } + }.start(); + //收集设备参数信息 + collectDeviceInfo(mContext); + + //打印异常log,以供分析调试 + ex.printStackTrace(); + //保存日志文件 + String path = saveCrashInfo2File(ex); + + Log.d(TAG, BROADCAST_ACTION); + Intent intent = new Intent(); + intent.setAction(BROADCAST_ACTION); + intent.putExtra("path", path); + intent.putExtra("pkgName", mContext.getPackageName()); + mContext.sendBroadcast(intent); + + return true; + } + + /** + * 收集设备参数信息 + * + * @param ctx 异常 + */ + private void collectDeviceInfo(Context ctx) { + try { + PackageManager pm = ctx.getPackageManager(); + PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES); + if (pi != null) { + String versionName = pi.versionName == null ? "null" : pi.versionName; + String versionCode = pi.versionCode + ""; + infos.put("versionName", versionName); + infos.put("versionCode", versionCode); + } + } catch (NameNotFoundException e) { + Log.e(TAG, "An error occur when collect package info", e); + } + Field[] fields = Build.class.getDeclaredFields(); + for (Field field : fields) { + try { + field.setAccessible(true); + infos.put(field.getName(), field.get(null).toString()); + Log.d(TAG, field.getName() + " : " + field.get(null)); + } catch (Exception e) { + Log.e(TAG, "An error occur when collect crash info", e); + } + } + } + + /** + * 保存错误信息到文件中 + * + * @param ex 异常 + * @return 返回文件名称, 便于将文件传送到服务器 + */ + private String saveCrashInfo2File(Throwable ex) { + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : infos.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + sb.append(key + "=" + value + "\n"); + } + + Writer writer = new StringWriter(); + PrintWriter printWriter = new PrintWriter(writer); + ex.printStackTrace(printWriter); + Throwable cause = ex.getCause(); + while (cause != null) { + cause.printStackTrace(printWriter); + cause = cause.getCause(); + } + printWriter.close(); + String result = writer.toString(); + sb.append(result); + try { + long timestamp = System.currentTimeMillis(); + String time = formatter.format(new Date()); + String pkgNamePath = packageName.replace(".", "_"); + String fileName = "crash_" + pkgNamePath + "_" + time + "_" + timestamp + ".log"; + String path = getCrashLogPath(); + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + File dir = new File(path); + if (!dir.exists()) { + boolean res = dir.mkdirs(); + Log.v(TAG, ("saveCrashInfo2File res: " + res)); + } + FileOutputStream fos = new FileOutputStream(path + fileName); + fos.write(sb.toString().getBytes()); + fos.close(); + } + return path + fileName; + } catch (Exception e) { + Log.e(TAG, "an error occur while writing file...", e); + } + return null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/handset/serialportsensor/utils/DateStyle.java b/app/src/main/java/com/handset/serialportsensor/utils/DateStyle.java new file mode 100644 index 0000000..71690b9 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/DateStyle.java @@ -0,0 +1,49 @@ +package com.handset.serialportsensor.utils; + +/** + * 从AndroidOne上导入的 + * Created by LiGang on 2016/6/1. + */ +public class DateStyle { + + /** + * 默认时间格式 + */ + public static final String MM_DD = "MM-dd"; + public static final String YYYY_MM = "yyyy-MM"; + public static final String YYYYMM = "yyyyMM"; + public static final String YYYY_MM_DD = "yyyy-MM-dd"; + public static final String MM_DD_HH_MM = "MM-dd HH:mm"; + public static final String MM_DD_HH_MM_SS = "MM-dd HH:mm:ss"; + public static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd-HH-mm"; + public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + + /** + * 英文时间格式 + */ + public static final String MM_DD_EN = "MM/dd"; + public static final String YYYY_MM_EN = "yyyy/MM"; + public static final String YYYY_MM_DD_EN = "yyyy/MM/dd"; + public static final String MM_DD_HH_MM_EN = "MM/DD HH:mm"; + public static final String MM_DD_HH_MM_SS_EN = "MM/dd HH:mm:ss"; + public static final String YYYY_MM_DD_HH_MM_EN = "yyyy/MM/dd HH:mm"; + public static final String YYYY_MM_DD_HH_MM_SS_EN = "yyyy/MM/dd HH:mm:ss"; + + /** + * 中文时间格式 + */ + public static final String MM_DD_CN = "MM月dd日"; + public static final String YYYY_MM_CN = "yyyy年MM月"; + public static final String YYYY_MM_DD_CN = "yyyy年MM月dd日"; + public static final String MM_DD_HH_MM_CN = "MM月dd日 HH:mm"; + public static final String MM_DD_HH_MM_SS_CN = "MM月dd日 HH:mm:ss"; + public static final String YYYY_MM_DD_HH_MM_CN = "yyyy年MM月dd日 HH:mm"; + public static final String YYYY_MM_DD_HH_MM_SS_CN = "yyyy年MM月dd日 HH:mm:ss"; + + + /** + * 具体时间格式 + */ + public static final String HH_MM = "HH:mm"; + public static final String HH_MM_SS = "HH:mm:ss"; +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/DateUtils.java b/app/src/main/java/com/handset/serialportsensor/utils/DateUtils.java new file mode 100644 index 0000000..d89644e --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/DateUtils.java @@ -0,0 +1,322 @@ +package com.handset.serialportsensor.utils; + +import android.annotation.SuppressLint; +import android.content.Context; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + * 日期显示,格式化。 + * Created by LiGang on 2016/6/1. + */ +@SuppressWarnings("ALL") +@SuppressLint("SimpleDateFormat") +public class DateUtils { + /** + * 获取当前时间 + * 格式 : "yyyy_MM_dd" + * + * @return + */ + public static String currentDateTime() { + return currentDateTime(DateStyle.YYYY_MM_DD); + } + + /** + * 获取当前时间 + * 指定样式 + * + * @param dateStyle 格式 + * @return + */ + public static String currentDateTime(String dateStyle) { + SimpleDateFormat formatter = new SimpleDateFormat(dateStyle); + return formatter.format(new Date()); + } + + /** + * 格式化时间 + * + * @param date 时间 + * @param style 格式 + * @return 格式化结果 + */ + public static String format(Date date, String style) { + SimpleDateFormat format = new SimpleDateFormat(style); + return format.format(date); + } + + /** + * 今天零点的时间 + * + * @param date + * @return + */ + public static Date startOfDate(Date date) { + long time = date.getTime() / (1000 * 3600 * 24) * (1000 * 3600 * 24) - TimeZone.getDefault().getRawOffset();// 今天零点零分零秒的毫秒数 + return new Date(time); + } + + /** + * 第一个时间是不是在第二个时间之前 + * + * @param date + * @param now + * @return + */ + public static boolean before(Date date, Date now) { + if (date.before(now)) { + return true; + } else { + long between = date.getTime() - now.getTime(); + + if (between > (24 * 3600000)) { + return false; + } + return true; + } + } + + /** + * 今天23:59:59的时间 + * + * @param date + * @return + */ + public static Date endOfDate(Date date) { + long time = date.getTime() / (1000 * 3600 * 24) * (1000 * 3600 * 24) - TimeZone.getDefault().getRawOffset() + 24 * 60 * 60 * 1000 - 1; + return new Date(time); + } + + /** + * 格式化timestamp格式的时间,以秒为单位 + * + * @param timestamp 秒 + * @param dateStyle 格式 + * @return 格式化结果 + */ + public static String formatSecondTimestamp(long timestamp, String dateStyle) { + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(timestamp * 1000); + return format(c.getTime(), dateStyle); + } + + /** + * 格式化timestamp格式的时间,以秒为单位 + * + * @param timestamp 毫秒 + * @param dateStyle 格式 + * @return 格式化结果 + */ + public static String formatMilliesTimestamp(long timestamp, String dateStyle) { + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(timestamp ); + return format(c.getTime(), dateStyle); + } + + + /** + * 根据时间戳,格式化日期,当天只返回时间,其他返回日期 + * + * @param timestamp 秒 + * @return 格式化的时间 + */ + public static String getCurrentTimeIFCurrentDayOrDate(long timestamp) { + Calendar now = Calendar.getInstance(); + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(timestamp * 1000); + if (c.get(Calendar.YEAR) == now.get(Calendar.YEAR) + && c.get(Calendar.MONTH) == now.get(Calendar.MONTH) + && c.get(Calendar.DATE) == now.get(Calendar.DATE)) { + return format(c.getTime(), DateStyle.HH_MM); + } + return format(c.getTime(), DateStyle.YYYY_MM_DD); + } + + /** + * 获取yyyy-MM-dd格式日期 + * + * @param context + * @param date + * @return + */ + public static String getDateFormatYYYYMMDD(Context context, Date date) { + if (context == null) return null; + SimpleDateFormat format = new SimpleDateFormat(DateStyle.YYYY_MM_DD); + return format.format(date); + } + + /** + * 把一个日期格式的字符串转化为日期 + * + * @param context + * @param dateStr + * @return + * @throws ParseException + */ + public static Date parseStringToDate(Context context, String dateStr) throws ParseException { + if (context == null || dateStr == null) return null; + SimpleDateFormat format = new SimpleDateFormat(DateStyle.YYYY_MM_DD); + return format.parse(dateStr); + } + + /** + * 将一个时间转换为提示性字符串 + * + * @param timeStamp 秒值 + * @return + */ + public static String convertTimeToFormat(long timeStamp) { + int current = (int) (System.currentTimeMillis() / 1000 - timeStamp); + Calendar calendar = Calendar.getInstance(); + String today = DateUtils.format(calendar.getTime(), "yyyy-MM-dd"); + String currentYear = DateUtils.format(calendar.getTime(), "yyyy"); + calendar.setTimeInMillis(timeStamp * 1000); + String publishDay = DateUtils.format(calendar.getTime(), "yyyy-MM-dd"); + String publishYear = DateUtils.format(calendar.getTime(), "yyyy"); + String publishMonth = DateUtils.format(calendar.getTime(), "MM-dd HH:mm"); + if (current < 60) { + return "刚刚"; + } else if (current < 3600) { + if (today.equals(publishDay)) { + return current / 60 + "分钟前"; + } else { + return publishMonth; + } + } else if (current < 86400) { + if (today.equals(publishDay)) { + return current / 3600 + "小时前"; + } else { + return publishMonth; + } + } else if (current < 31536000) { + if (publishYear.equals(currentYear)) { + return publishMonth; + } else { + return publishDay; + } + } else { + return publishDay; + } + } + + /** + * 将一个日期转换为提示性时间字符串 + * + * @param date 日期 + * @return + */ + public static String formatDateTime(Date date) { + String text; + long dateTime = date.getTime(); + if (isSameDay(dateTime)) { + Calendar calendar = GregorianCalendar.getInstance(); + if (inOneMinute(dateTime, calendar.getTimeInMillis())) { + return "刚刚"; + } else if (inOneHour(dateTime, calendar.getTimeInMillis())) { + return String.format("%d分钟之前", Math.abs(dateTime - calendar.getTimeInMillis()) / 60000); + } else { + calendar.setTime(date); + text = "HH:mm"; + } + } else if (isYesterday(dateTime)) { + text = "昨天 HH:mm"; + } else if (isSameYear(dateTime)) { + text = "M-d HH:mm"; + } else { + text = "yyyy-M-d HH:mm"; + } + + // 注意,如果使用android.text.format.DateFormat这个工具类,在API 17之前它只支持adEhkMmszy + return new SimpleDateFormat(text, Locale.CHINA).format(date); + } + + /** + * 时间间隔是否在1min内 + * + * @param time1 毫秒 + * @param time2 毫秒 + * @return + */ + private static boolean inOneMinute(long time1, long time2) { + return Math.abs(time1 - time2) < 60000; + } + + /** + * 时间间隔是否在1h内 + * + * @param time1 毫秒 + * @param time2 毫秒 + * @return + */ + private static boolean inOneHour(long time1, long time2) { + return Math.abs(time1 - time2) < 3600000; + } + + /** + * 是否是同一天 + * + * @param time 毫秒 + * @return + */ + private static boolean isSameDay(long time) { + long startTime = floorDay(Calendar.getInstance()).getTimeInMillis(); + long endTime = ceilDay(Calendar.getInstance()).getTimeInMillis(); + return time > startTime && time < endTime; + } + + /** + * 是否是昨天 + * + * @param time 毫秒 + * @return + */ + private static boolean isYesterday(long time) { + Calendar startCal; + startCal = floorDay(Calendar.getInstance()); + startCal.add(Calendar.DAY_OF_MONTH, -1); + long startTime = startCal.getTimeInMillis(); + + Calendar endCal; + endCal = ceilDay(Calendar.getInstance()); + endCal.add(Calendar.DAY_OF_MONTH, -1); + long endTime = endCal.getTimeInMillis(); + return time > startTime && time < endTime; + } + + /** + * 是否是同一年 + * + * @param time 毫秒 + * @return + */ + private static boolean isSameYear(long time) { + Calendar startCal; + startCal = floorDay(Calendar.getInstance()); + startCal.set(Calendar.MONTH, Calendar.JANUARY); + startCal.set(Calendar.DAY_OF_MONTH, 1); + return time >= startCal.getTimeInMillis(); + } + + private static Calendar floorDay(Calendar startCal) { + startCal.set(Calendar.HOUR_OF_DAY, 0); + startCal.set(Calendar.MINUTE, 0); + startCal.set(Calendar.SECOND, 0); + startCal.set(Calendar.MILLISECOND, 0); + return startCal; + } + + private static Calendar ceilDay(Calendar endCal) { + endCal.set(Calendar.HOUR_OF_DAY, 23); + endCal.set(Calendar.MINUTE, 59); + endCal.set(Calendar.SECOND, 59); + endCal.set(Calendar.MILLISECOND, 999); + return endCal; + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/EmulatorUtils.java b/app/src/main/java/com/handset/serialportsensor/utils/EmulatorUtils.java new file mode 100644 index 0000000..c3200e1 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/EmulatorUtils.java @@ -0,0 +1,144 @@ +package com.handset.serialportsensor.utils; + +import android.os.Build; +import android.os.Environment; +import android.util.Log; + +import java.io.File; + +public class EmulatorUtils { + private static final String TAG = "EmulatorDetector"; + + private static int rating = -1; + + /** + * Detects if app is currenly running on emulator, or real device. + * @return true for emulator, false for real devices + */ + public static boolean isEmulator() { + int newRating = 0; + if(rating < 0) { + if (Build.PRODUCT.contains("sdk") || + Build.PRODUCT.contains("Andy") || + Build.PRODUCT.contains("ttVM_Hdragon") || + Build.PRODUCT.contains("google_sdk") || + Build.PRODUCT.contains("Droid4X") || + Build.PRODUCT.contains("nox") || + Build.PRODUCT.contains("sdk_x86") || + Build.PRODUCT.contains("sdk_google") || + Build.PRODUCT.contains("vbox86p")) { + newRating++; + } + + if (Build.MANUFACTURER.equals("unknown") || + Build.MANUFACTURER.equals("Genymotion") || + Build.MANUFACTURER.contains("Andy") || + Build.MANUFACTURER.contains("MIT") || + Build.MANUFACTURER.contains("nox") || + Build.MANUFACTURER.contains("TiantianVM")){ + newRating++; + } + + if (Build.BRAND.equals("generic") || + Build.BRAND.equals("generic_x86") || + Build.BRAND.equals("TTVM") || + Build.BRAND.contains("Andy")) { + newRating++; + } + + if (Build.DEVICE.contains("generic") || + Build.DEVICE.contains("generic_x86") || + Build.DEVICE.contains("Andy") || + Build.DEVICE.contains("ttVM_Hdragon") || + Build.DEVICE.contains("Droid4X") || + Build.DEVICE.contains("nox") || + Build.DEVICE.contains("generic_x86_64") || + Build.DEVICE.contains("vbox86p")) { + newRating++; + } + + if (Build.MODEL.equals("sdk") || + Build.MODEL.equals("google_sdk") || + Build.MODEL.contains("Droid4X") || + Build.MODEL.contains("TiantianVM") || + Build.MODEL.contains("Andy") || + Build.MODEL.equals("Android SDK built for x86_64") || + Build.MODEL.equals("Android SDK built for x86")) { + newRating++; + } + + if (Build.HARDWARE.equals("goldfish") || + Build.HARDWARE.equals("vbox86") || + Build.HARDWARE.contains("nox") || + Build.HARDWARE.contains("ttVM_x86")) { + newRating++; + } + + if (Build.FINGERPRINT.contains("generic/sdk/generic") || + Build.FINGERPRINT.contains("generic_x86/sdk_x86/generic_x86") || + Build.FINGERPRINT.contains("Andy") || + Build.FINGERPRINT.contains("ttVM_Hdragon") || + Build.FINGERPRINT.contains("generic_x86_64") || + Build.FINGERPRINT.contains("generic/google_sdk/generic") || + Build.FINGERPRINT.contains("vbox86p") || + Build.FINGERPRINT.contains("generic/vbox86p/vbox86p")) { + newRating++; + } + + try { + String opengl = android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_RENDERER); + if (opengl != null){ + if( opengl.contains("Bluestacks") || + opengl.contains("Translator") + ) + newRating += 10; + } + } catch (Exception e) { + e.printStackTrace(); + } + + try { + File sharedFolder = new File(Environment + .getExternalStorageDirectory().toString() + + File.separatorChar + + "windows" + + File.separatorChar + + "BstSharedFolder"); + + if (sharedFolder.exists()) { + newRating += 10; + } + } catch (Exception e) { + e.printStackTrace(); + } + rating = newRating; + } + return rating > 3; + } + + /** + * Returns string with human-readable listing of Build.* parameters used in {@link #isEmulator()} method. + * @return all involved Build.* parameters and its values + */ + public static String getDeviceListing() { + return "Build.PRODUCT: " + Build.PRODUCT + "\n" + + "Build.MANUFACTURER: " + Build.MANUFACTURER + "\n" + + "Build.BRAND: " + Build.BRAND + "\n" + + "Build.DEVICE: " + Build.DEVICE + "\n" + + "Build.MODEL: " + Build.MODEL + "\n" + + "Build.HARDWARE: " + Build.HARDWARE + "\n" + + "Build.FINGERPRINT: " + Build.FINGERPRINT + "\n" + + "Build.TAGS: " + android.os.Build.TAGS + "\n" + + "GL_RENDERER: " +android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_RENDERER) + "\n" + + "GL_VENDOR: " +android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_VENDOR) + "\n" + + "GL_VERSION: " +android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_VERSION) + "\n" + + "GL_EXTENSIONS: " +android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_EXTENSIONS) + "\n"; + } + + /** + * Prints all Build.* parameters used in {@link #isEmulator()} method to logcat. + */ + public static void logcat() { + Log.d(TAG, getDeviceListing()); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/ExcelMa.java b/app/src/main/java/com/handset/serialportsensor/utils/ExcelMa.java new file mode 100644 index 0000000..35c7c69 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/ExcelMa.java @@ -0,0 +1,368 @@ +package com.handset.serialportsensor.utils; + +import android.os.Environment; +import android.text.TextUtils; +import android.util.Log; + + +import com.handset.serialportsensor.bean.Sensor; +import com.handset.serialportsensor.bean.TestRecordsTotal; + +import org.apache.poi.hssf.usermodel.HSSFDateUtil; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellValue; +import org.apache.poi.ss.usermodel.FormulaEvaluator; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.WorkbookUtil; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.kymjs.kjframe.KJDB; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.List; + +import static com.handset.serialportsensor.utils.DateStyle.YYYY_MM_DD_HH_MM_SS; + + +/** + * Created by zy on 2019/3/4. + */ + +public class ExcelMa { + private final static String TAG = "ExcelMa"; + + public static String getSavePath() { + String path = Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + "htjc" + File.separator + "sensor" + File.separator + "export" + File.separator; + File dir = new File(path); + if (!dir.exists()) { + dir.mkdirs(); + } + return path; + } + + public static File getSavePathFile() { + String path = Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + "htjc" + File.separator + "sensor" + File.separator + "export" + File.separator; + File dir = new File(path); + if (!dir.exists()) { + dir.mkdirs(); + } + return dir; + } + + public void createExcel() { + String name = getSavePath() + "workbook.xlsx"; + Workbook wb = new XSSFWorkbook(); + FileOutputStream fileOut = null; + try { + fileOut = new FileOutputStream(name); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + try { + wb.write(fileOut); + fileOut.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + + public void stopExport() { + exportStatus = false; + } + + public void write(List testRecordsTotals, PersistHelper.ExportCallback exportCallback, String timePerfix) { + exportStatus = true; + int counts = testRecordsTotals.size(); + int remain = counts; + for (int i = 0; i < counts; i++) { + if (!exportStatus) { + break; + } + remain = counts - i; + exportCallback.exportProgress(counts, remain); + write(testRecordsTotals.get(i), timePerfix); + remain = counts - i - 1; + exportCallback.exportProgress(counts, remain); + if (!exportStatus) { + break; + } + } + exportCallback.finish(counts, remain); + } + + public void write(TestRecordsTotal t, Sensor s, String tiems) { + File cacheDir = getSavePathFile(); + String sheetNama = t.sensor_id + "(" + tiems + ")"; + String outFileName = "检测结果(" + tiems + ").xlsx"; + File outFile = new File(cacheDir, outFileName); + InputStream stream = null; + try { + stream = new FileInputStream(outFile); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + XSSFWorkbook workbook = null; + try { + if (stream != null) { + workbook = new XSSFWorkbook(stream); + } + } catch (IOException e) { + e.printStackTrace(); + } + if (workbook == null) { + workbook = new XSSFWorkbook(); + Log.d(TAG, "write [t, s]:" + "create workbook"); + } + XSSFSheet sheet = workbook.getSheet(sheetNama); + if (sheet == null) { + sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName(sheetNama)); + Log.d(TAG, "write [t, s]:" + "create sheet" + sheetNama); + } + int rows = sheet.getPhysicalNumberOfRows(); + Log.d(TAG, "write [t, s]rows:" + rows); + if (rows == 0) { + XSSFRow row = sheet.createRow(0); + row.createCell(0).setCellValue("采样时间戳"); + row.createCell(1).setCellValue("高精度温度(℃)温度"); + row.createCell(2).setCellValue("高精度湿度(%RH)"); + row.createCell(3).setCellValue("高精度内压(kPa)"); + row.createCell(4).setCellValue("高精度外压(kPa)"); + row.createCell(5).setCellValue("差压(kPa"); + row.createCell(6).setCellValue("20℃湿度(%RH)"); + row.createCell(7).setCellValue("20℃压力(kPa)"); + row.createCell(8).setCellValue("传感器编号"); + row.createCell(9).setCellValue("弹型"); + row.createCell(10).setCellValue("弹号"); + row.createCell(11).setCellValue("筒号"); + row.createCell(12).setCellValue("弹筒使用次数"); + row.createCell(13).setCellValue("波特率"); + rows++; + } + + XSSFRow row = sheet.createRow(rows); + row.createCell(0).setCellValue(DateUtils.formatMilliesTimestamp(t.end_time, YYYY_MM_DD_HH_MM_SS)); + row.createCell(1).setCellValue(t.temp); + row.createCell(2).setCellValue(t.Hum); + row.createCell(3).setCellValue(t.pressurein); + row.createCell(4).setCellValue(t.pressureout); + row.createCell(5).setCellValue(t.pressure_yacha); + row.createCell(6).setCellValue(t.Hum20); + row.createCell(7).setCellValue(t.pressurein20); + row.createCell(8).setCellValue(t.sensor_id); + row.createCell(9).setCellValue(s.egg_type); + row.createCell(10).setCellValue(s.egg_id); + row.createCell(11).setCellValue(s.tupe_id); + row.createCell(12).setCellValue(t.tupe_use_times); + row.createCell(13).setCellValue(t.botelv); + + FileOutputStream fileOut = null; + try { + fileOut = new FileOutputStream(outFile); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + try { + workbook.write(fileOut); + fileOut.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void write(TestRecordsTotal t, String timePerfix) { + List s = KJDB.getDefaultInstance().findAllByWhere(Sensor.class, "sensor_id = " + t.sensor_id + ""); + if (s == null || s.size() == 0) { + Log.e(TAG, "write [t]:" + "save test record failed, no sensor id info" + t.sensor_id + ""); + return; + } + write(t, s.get(0), timePerfix); + } + + + protected String getCellAsString(Row row, int c, FormulaEvaluator formulaEvaluator) { + String value = ""; + try { + Cell cell = row.getCell(c); + CellValue cellValue = formulaEvaluator.evaluate(cell); + switch (cellValue.getCellType()) { + case Cell.CELL_TYPE_BOOLEAN: + value = "" + cellValue.getBooleanValue(); + break; + case Cell.CELL_TYPE_NUMERIC: + double numericValue = cellValue.getNumberValue(); + if (HSSFDateUtil.isCellDateFormatted(cell)) { + double date = cellValue.getNumberValue(); + SimpleDateFormat formatter = + new SimpleDateFormat("dd/MM/yy"); + value = formatter.format(HSSFDateUtil.getJavaDate(date)); + } else { + value = "" + numericValue; + } + break; + case Cell.CELL_TYPE_STRING: + value = "" + cellValue.getStringValue(); + break; + default: + } + } catch (NullPointerException e) { + /* proper error handling should be here */ + e.printStackTrace(); + } + return value; + } + + public void onWriteClick(TestRecordsTotal testRecordsTotal) { + XSSFWorkbook workbook = new XSSFWorkbook(); + XSSFSheet sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName("mysheet")); + + for (int i = 0; i < 10; i++) { + Row row = sheet.createRow(i); + Cell cell = row.createCell(0); + cell.setCellValue(i); + } + String outFileName = "filetoshare.xlsx"; + try { + + File cacheDir = getSavePathFile(); + File outFile = new File(cacheDir, outFileName); + OutputStream outputStream = new FileOutputStream(outFile.getAbsolutePath()); + workbook.write(outputStream); + outputStream.flush(); + outputStream.close(); + + //share(outFileName, getApplicationContext()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + //导出线程的状态 + volatile boolean exportStatus = true; + + public void onReadClick(File file, PersistHelper.ExportCallback exportCallback) { + exportStatus = true; + PersistHelper.resetDB(); + int dataItems = 0; + int remain = dataItems; + Log.d(TAG, "onReadClick [view]:"); + try { + InputStream stream = new FileInputStream(file); + XSSFWorkbook workbook = new XSSFWorkbook(stream); + int sheetsNums = workbook.getNumberOfSheets(); + Log.d(TAG, "onReadClick [file]sheetsNums:" + sheetsNums); + dataItems = 0; + for (int i = 0; i < sheetsNums; i++) { + dataItems += workbook.getSheetAt(i).getPhysicalNumberOfRows() - 1; + } + Log.d(TAG, "onReadClick [file]dataItems:" + dataItems); + remain = dataItems; + exportCallback.exportProgress(dataItems, remain); + Calendar calendar = Calendar.getInstance(); + for (int i = 0; i < sheetsNums; i++) { + if (!exportStatus) { + break; + } + Sensor s = new Sensor(); + XSSFSheet sheet = workbook.getSheetAt(i); + int rowsCount = sheet.getPhysicalNumberOfRows(); + FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator(); + for (int r = 1; r < rowsCount; r++) { + if (!exportStatus) { + break; + } + Row row = sheet.getRow(r); + int cellsCount = row.getPhysicalNumberOfCells(); + TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); + testRecordsTotal.id = PersistHelper.generateNextTestId(); + + String et = getCellAsString(row, 0, formulaEvaluator); + //2019-03-05 14:52:42 + calendar.set( + Integer.parseInt(et.substring(0, 4)), + Integer.parseInt(et.substring(5, 7)) - 1, + Integer.parseInt(et.substring(8, 10)), + Integer.parseInt(et.substring(11, 13)), + Integer.parseInt(et.substring(14, 16)), + Integer.parseInt(et.substring(17, 19))); + String te = getCellAsString(row, 1, formulaEvaluator); + testRecordsTotal.temp = Float.parseFloat(te); + String hum = getCellAsString(row, 2, formulaEvaluator); + testRecordsTotal.Hum = Float.parseFloat(hum); + String neiya = getCellAsString(row, 3, formulaEvaluator); + testRecordsTotal.pressurein = Float.parseFloat(neiya); + String waiya = getCellAsString(row, 4, formulaEvaluator); + testRecordsTotal.pressureout = Float.parseFloat(waiya); + String yacha = getCellAsString(row, 5, formulaEvaluator); + testRecordsTotal.pressure_yacha = Float.parseFloat(yacha); + String shidu20 = getCellAsString(row, 6, formulaEvaluator); + testRecordsTotal.Hum20 = Float.parseFloat(shidu20); + String yali20 = getCellAsString(row, 7, formulaEvaluator); + testRecordsTotal.pressurein20 = Float.parseFloat(yali20); + testRecordsTotal.end_time = calendar.getTimeInMillis(); + calendar.setTimeInMillis(testRecordsTotal.end_time); + testRecordsTotal.day_t = calendar.get(Calendar.DAY_OF_YEAR) + calendar.get(Calendar.YEAR) * 1000; + String sensor_id = getCellAsString(row, 8, formulaEvaluator); + if (sensor_id.length() > 8) { + sensor_id = sensor_id.replace(".", "").substring(0, 8); + } + testRecordsTotal.sensor_id = Long.parseLong(sensor_id); + s.sensor_id = testRecordsTotal.sensor_id; + String danxing = getCellAsString(row, 9, formulaEvaluator); + s.egg_type = danxing; + String danhao = getCellAsString(row, 10, formulaEvaluator); + s.egg_id = danhao; + String tonghao = getCellAsString(row, 11, formulaEvaluator); + s.tupe_id = tonghao; + String tupeUsetimes = getCellAsString(row, 12, formulaEvaluator); + if (!TextUtils.isEmpty(tupeUsetimes)) { + + if (tupeUsetimes.endsWith(".0")) { + tupeUsetimes = tupeUsetimes.replace(".0", ""); + } + s.tv_tupe_use_times = tupeUsetimes; + testRecordsTotal.tupe_use_times = tupeUsetimes; + } + + String botelv = getCellAsString(row, 13, formulaEvaluator); + testRecordsTotal.botelv = botelv; + + if (KJDB.getDefaultInstance().findById(testRecordsTotal.id, TestRecordsTotal.class) != null) { + KJDB.getDefaultInstance().update(testRecordsTotal); + } else { + KJDB.getDefaultInstance().save(testRecordsTotal); + } + remain--; + exportCallback.exportProgress(dataItems, remain); + if (!exportStatus) { + break; + } + } + if (KJDB.getDefaultInstance().findById(s.id, Sensor.class) != null) { + KJDB.getDefaultInstance().update(s); + } else { + KJDB.getDefaultInstance().save(s); + } + } + stream.close(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + + } + + exportCallback.finish(dataItems, remain); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/ExcelUtils.java b/app/src/main/java/com/handset/serialportsensor/utils/ExcelUtils.java new file mode 100644 index 0000000..28b01ef --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/ExcelUtils.java @@ -0,0 +1,364 @@ +package com.handset.serialportsensor.utils; + +import android.os.Environment; +import android.text.TextUtils; +import android.util.Log; + +import com.handset.serialportsensor.bean.Sensor; +import com.handset.serialportsensor.bean.TestRecordsTotal; + +import org.apache.poi.hssf.usermodel.HSSFDateUtil; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellValue; +import org.apache.poi.ss.usermodel.FormulaEvaluator; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.WorkbookUtil; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.kymjs.kjframe.KJDB; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.List; + +/** + * Created by zy on 2019/3/4. + */ + +public class ExcelUtils { + private final static String TAG = "ExcelMa"; + + public static String getSavePath() { + String path = Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + "htjc" + File.separator + "sensor" + File.separator + "export" + File.separator; + File dir = new File(path); + if (!dir.exists()) { + dir.mkdirs(); + } + return path; + } + + public static File getSavePathFile() { + String path = Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + "htjc" + File.separator + "sensor" + File.separator + "export" + File.separator; + File dir = new File(path); + if (!dir.exists()) { + dir.mkdirs(); + } + return dir; + } + + public void createExcel() { + String name = getSavePath() + "workbook.xlsx"; + Workbook wb = new XSSFWorkbook(); + FileOutputStream fileOut = null; + try { + fileOut = new FileOutputStream(name); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + try { + wb.write(fileOut); + fileOut.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + + public void stopExport() { + exportStatus = false; + } + + public void write(List testRecordsTotals, PersistHelper.ExportCallback exportCallback, String timePerfix) { + exportStatus = true; + int counts = testRecordsTotals.size(); + int remain = counts; + for (int i = 0; i < counts; i++) { + if (!exportStatus) { + break; + } + remain = counts - i; + exportCallback.exportProgress(counts, remain); + write(testRecordsTotals.get(i), timePerfix); + remain = counts - i - 1; + exportCallback.exportProgress(counts, remain); + if (!exportStatus) { + break; + } + } + exportCallback.finish(counts, remain); + } + + public void write(TestRecordsTotal t, Sensor s, String tiems) { + File cacheDir = getSavePathFile(); + String sheetNama = t.sensor_id + "(" + tiems + ")"; + String outFileName = "检测结果(" + tiems + ").xlsx"; + File outFile = new File(cacheDir, outFileName); + InputStream stream = null; + try { + stream = new FileInputStream(outFile); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + XSSFWorkbook workbook = null; + try { + if (stream != null) { + workbook = new XSSFWorkbook(stream); + } + } catch (IOException e) { + e.printStackTrace(); + } + if (workbook == null) { + workbook = new XSSFWorkbook(); + Log.d(TAG, "write [t, s]:" + "create workbook"); + } + XSSFSheet sheet = workbook.getSheet(sheetNama); + if (sheet == null) { + sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName(sheetNama)); + Log.d(TAG, "write [t, s]:" + "create sheet" + sheetNama); + } + int rows = sheet.getPhysicalNumberOfRows(); + Log.d(TAG, "write [t, s]rows:" + rows); + if (rows == 0) { + XSSFRow row = sheet.createRow(0); + row.createCell(0).setCellValue("采样时间戳"); + row.createCell(1).setCellValue("高精度温度(℃)温度"); + row.createCell(2).setCellValue("高精度湿度(%RH)"); + row.createCell(3).setCellValue("高精度内压(kPa)"); + row.createCell(4).setCellValue("高精度外压(kPa)"); + row.createCell(5).setCellValue("差压(kPa"); + row.createCell(6).setCellValue("20℃湿度(%RH)"); + row.createCell(7).setCellValue("20℃压力(kPa)"); + row.createCell(8).setCellValue("传感器编号"); + row.createCell(9).setCellValue("弹型"); + row.createCell(10).setCellValue("弹号"); + row.createCell(11).setCellValue("筒号"); + row.createCell(12).setCellValue("弹筒使用次数"); + row.createCell(13).setCellValue("波特率"); + rows++; + } + + XSSFRow row = sheet.createRow(rows); + row.createCell(0).setCellValue(DateUtils.formatMilliesTimestamp(t.end_time, "yyyy-MM-dd HH:mm:ss")); + row.createCell(1).setCellValue(t.temp); + row.createCell(2).setCellValue(t.Hum); + row.createCell(3).setCellValue(t.pressurein); + row.createCell(4).setCellValue(t.pressureout); + row.createCell(5).setCellValue(t.pressure_yacha); + row.createCell(6).setCellValue(t.Hum20); + row.createCell(7).setCellValue(t.pressurein20); + row.createCell(8).setCellValue(t.sensor_id); + row.createCell(9).setCellValue(s.egg_type); + row.createCell(10).setCellValue(s.egg_id); + row.createCell(11).setCellValue(s.tupe_id); + row.createCell(12).setCellValue(t.tupe_use_times); + row.createCell(13).setCellValue(t.botelv); + + FileOutputStream fileOut = null; + try { + fileOut = new FileOutputStream(outFile); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + try { + workbook.write(fileOut); + fileOut.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void write(TestRecordsTotal t, String timePerfix) { + List s = KJDB.getDefaultInstance().findAllByWhere(Sensor.class, "sensor_id = " + t.sensor_id + ""); + if (s == null || s.size() == 0) { + Log.e(TAG, "write [t]:" + "save test record failed, no sensor id info" + t.sensor_id + ""); + return; + } + write(t, s.get(0), timePerfix); + } + + + protected String getCellAsString(Row row, int c, FormulaEvaluator formulaEvaluator) { + String value = ""; + try { + Cell cell = row.getCell(c); + CellValue cellValue = formulaEvaluator.evaluate(cell); + switch (cellValue.getCellType()) { + case Cell.CELL_TYPE_BOOLEAN: + value = "" + cellValue.getBooleanValue(); + break; + case Cell.CELL_TYPE_NUMERIC: + double numericValue = cellValue.getNumberValue(); + if (HSSFDateUtil.isCellDateFormatted(cell)) { + double date = cellValue.getNumberValue(); + SimpleDateFormat formatter = + new SimpleDateFormat("dd/MM/yy"); + value = formatter.format(HSSFDateUtil.getJavaDate(date)); + } else { + value = "" + numericValue; + } + break; + case Cell.CELL_TYPE_STRING: + value = "" + cellValue.getStringValue(); + break; + default: + } + } catch (NullPointerException e) { + /* proper error handling should be here */ + e.printStackTrace(); + } + return value; + } + + public void onWriteClick(TestRecordsTotal testRecordsTotal) { + XSSFWorkbook workbook = new XSSFWorkbook(); + XSSFSheet sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName("mysheet")); + + for (int i = 0; i < 10; i++) { + Row row = sheet.createRow(i); + Cell cell = row.createCell(0); + cell.setCellValue(i); + } + String outFileName = "filetoshare.xlsx"; + try { + + File cacheDir = getSavePathFile(); + File outFile = new File(cacheDir, outFileName); + OutputStream outputStream = new FileOutputStream(outFile.getAbsolutePath()); + workbook.write(outputStream); + outputStream.flush(); + outputStream.close(); + + //share(outFileName, getApplicationContext()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + //导出线程的状态 + volatile boolean exportStatus = true; + + public void onReadClick(File file, PersistHelper.ExportCallback exportCallback) { + exportStatus = true; + PersistHelper.resetDB(); + int dataItems = 0; + int remain = dataItems; + Log.d(TAG, "onReadClick [view]:"); + try { + InputStream stream = new FileInputStream(file); + XSSFWorkbook workbook = new XSSFWorkbook(stream); + int sheetsNums = workbook.getNumberOfSheets(); + Log.d(TAG, "onReadClick [file]sheetsNums:" + sheetsNums); + dataItems = 0; + for (int i = 0; i < sheetsNums; i++) { + dataItems += workbook.getSheetAt(i).getPhysicalNumberOfRows() - 1; + } + Log.d(TAG, "onReadClick [file]dataItems:" + dataItems); + remain = dataItems; + exportCallback.exportProgress(dataItems, remain); + Calendar calendar = Calendar.getInstance(); + for (int i = 0; i < sheetsNums; i++) { + if (!exportStatus) { + break; + } + Sensor s = new Sensor(); + XSSFSheet sheet = workbook.getSheetAt(i); + int rowsCount = sheet.getPhysicalNumberOfRows(); + FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator(); + for (int r = 1; r < rowsCount; r++) { + if (!exportStatus) { + break; + } + Row row = sheet.getRow(r); + int cellsCount = row.getPhysicalNumberOfCells(); + TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); + testRecordsTotal.id = PersistHelper.generateNextTestId(); + + String et = getCellAsString(row, 0, formulaEvaluator); + //2019-03-05 14:52:42 + calendar.set( + Integer.parseInt(et.substring(0, 4)), + Integer.parseInt(et.substring(5, 7)) - 1, + Integer.parseInt(et.substring(8, 10)), + Integer.parseInt(et.substring(11, 13)), + Integer.parseInt(et.substring(14, 16)), + Integer.parseInt(et.substring(17, 19))); + String te = getCellAsString(row, 1, formulaEvaluator); + testRecordsTotal.temp = Float.parseFloat(te); + String hum = getCellAsString(row, 2, formulaEvaluator); + testRecordsTotal.Hum = Float.parseFloat(hum); + String neiya = getCellAsString(row, 3, formulaEvaluator); + testRecordsTotal.pressurein = Float.parseFloat(neiya); + String waiya = getCellAsString(row, 4, formulaEvaluator); + testRecordsTotal.pressureout = Float.parseFloat(waiya); + String yacha = getCellAsString(row, 5, formulaEvaluator); + testRecordsTotal.pressure_yacha = Float.parseFloat(yacha); + String shidu20 = getCellAsString(row, 6, formulaEvaluator); + testRecordsTotal.Hum20 = Float.parseFloat(shidu20); + String yali20 = getCellAsString(row, 7, formulaEvaluator); + testRecordsTotal.pressurein20 = Float.parseFloat(yali20); + testRecordsTotal.end_time = calendar.getTimeInMillis(); + calendar.setTimeInMillis(testRecordsTotal.end_time); + testRecordsTotal.day_t = calendar.get(Calendar.DAY_OF_YEAR) + calendar.get(Calendar.YEAR) * 1000; + String sensor_id = getCellAsString(row, 8, formulaEvaluator); + if (sensor_id.length() > 8) { + sensor_id = sensor_id.replace(".", "").substring(0, 8); + } + testRecordsTotal.sensor_id = Long.parseLong(sensor_id); + s.sensor_id = testRecordsTotal.sensor_id; + String danxing = getCellAsString(row, 9, formulaEvaluator); + s.egg_type = danxing; + String danhao = getCellAsString(row, 10, formulaEvaluator); + s.egg_id = danhao; + String tonghao = getCellAsString(row, 11, formulaEvaluator); + s.tupe_id = tonghao; + String tupeUsetimes = getCellAsString(row, 12, formulaEvaluator); + if (!TextUtils.isEmpty(tupeUsetimes)) { + + if (tupeUsetimes.endsWith(".0")) { + tupeUsetimes = tupeUsetimes.replace(".0", ""); + } + s.tv_tupe_use_times = tupeUsetimes; + testRecordsTotal.tupe_use_times = tupeUsetimes; + } + + String botelv = getCellAsString(row, 13, formulaEvaluator); + testRecordsTotal.botelv = botelv; + + if (KJDB.getDefaultInstance().findById(testRecordsTotal.id, TestRecordsTotal.class) != null) { + KJDB.getDefaultInstance().update(testRecordsTotal); + } else { + KJDB.getDefaultInstance().save(testRecordsTotal); + } + remain--; + exportCallback.exportProgress(dataItems, remain); + if (!exportStatus) { + break; + } + } + if (KJDB.getDefaultInstance().findById(s.id, Sensor.class) != null) { + KJDB.getDefaultInstance().update(s); + } else { + KJDB.getDefaultInstance().save(s); + } + } + stream.close(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + + } + + exportCallback.finish(dataItems, remain); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/PersistHelper.java b/app/src/main/java/com/handset/serialportsensor/utils/PersistHelper.java new file mode 100644 index 0000000..60accb8 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/PersistHelper.java @@ -0,0 +1,377 @@ +package com.handset.serialportsensor.utils; + +import android.content.Context; +import android.util.Log; +import android.util.SparseArray; + +import com.handset.serialportsensor.bean.Sensor; +import com.handset.serialportsensor.bean.TestRecordsTotal; + +import org.kymjs.kjframe.KJDB; + +import java.text.DecimalFormat; +import java.util.Calendar; +import java.util.List; + +/** + * Created by zy on 2019/2/24. + */ + +public class PersistHelper { + private static final String logTag = "HANDSET-JE002-EX"; + private static Context sContext; + + private static Sensor mSensor = null; + private static ExcelUtils excelUtils; + + public static void init(Context context) { + sContext = context; + excelUtils = new ExcelUtils(); + } + + + public static void generateSimulateData() { + KJDB.getDefaultInstance().deleteByWhere(Sensor.class, "1=1"); + KJDB.getDefaultInstance().deleteByWhere(TestRecordsTotal.class, "1=1"); + initSensor(); + } + + private static void initSensor() { + Sensor sensor = new Sensor(); + sensor.id = 1; + sensor.egg_id = "EGG11234"; + sensor.sensor_id = 19011111; + sensor.egg_type = "EGGA1234"; + sensor.tupe_id = "TUPEA1234"; + KJDB.getDefaultInstance().save(sensor); + sensor.id = 2; + sensor.egg_id = "EGG21234"; + sensor.sensor_id = 19011112; + sensor.egg_type = "EGGB1234"; + sensor.tupe_id = "TUPEB1234"; + KJDB.getDefaultInstance().save(sensor); + + TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); + long a = 315360000000L; + testRecordsTotal.end_time = System.currentTimeMillis() - a; + testRecordsTotal.Hum = 80; + testRecordsTotal.sensor_id = 19011111; + testRecordsTotal.pressure_yacha = 100; + testRecordsTotal.pressurein = 90; + testRecordsTotal.pressureout = 120; + testRecordsTotal.temp = 50; + testRecordsTotal.Hum20 = 90; + testRecordsTotal.pressurein20 = 20; + testRecordsTotal.tupe_use_times = "10"; + int i = 1; + Calendar c = Calendar.getInstance(); + for (; i < 5000; i++) { + testRecordsTotal.id = i; + testRecordsTotal.end_time += 24 * 3600000; + c.setTimeInMillis(testRecordsTotal.end_time); + testRecordsTotal.day_t = c.get(Calendar.DAY_OF_YEAR) + c.get(Calendar.YEAR) * 1000; + KJDB.getDefaultInstance().save(testRecordsTotal); + if (i % 100 == 0) { + Log.d(logTag, "initSensor []:" + i); + } + } + + testRecordsTotal.sensor_id = 19011112; + for (; i < 10000; i++) { + testRecordsTotal.id = i; + testRecordsTotal.end_time += 24 * 3600000; + c.setTimeInMillis(testRecordsTotal.end_time); + testRecordsTotal.day_t = c.get(Calendar.DAY_OF_YEAR) + c.get(Calendar.YEAR) * 1000; + KJDB.getDefaultInstance().save(testRecordsTotal); + if (i % 100 == 0) { + Log.d(logTag, "initSensor []:" + i); + } + } + } + + public static void resetDB() { + KJDB.getDefaultInstance().deleteByWhere(Sensor.class, "1=1"); + KJDB.getDefaultInstance().deleteByWhere(TestRecordsTotal.class, "1=1"); + SPUtils.getInstance(sContext).put("current_test_id", -1l); + } + + public static long generateNextTestId() { + long currentTestId = SPUtils.getInstance(sContext).get("current_test_id", -1L); + long newId = currentTestId == -1 || currentTestId >= 10000000 ? 1 : currentTestId + 1; + TestRecordsTotal old = KJDB.getDefaultInstance().findById(newId, TestRecordsTotal.class); + if (old != null) { + KJDB.getDefaultInstance().delete(old); + } + SPUtils.getInstance(sContext).put("current_test_id", newId); + return newId; + } + + private static long NextTestIdCC() { + long currentTestId = SPUtils.getInstance(sContext).get("current_test_id", -1l); + long newId = currentTestId - 1; + if (newId == -1 || newId == 0 || currentTestId >= 10000000) { + newId = 0; + } + + TestRecordsTotal old = KJDB.getDefaultInstance().findById(currentTestId, TestRecordsTotal.class); + if (old != null) { + KJDB.getDefaultInstance().delete(old); + } + SPUtils.getInstance(sContext).put("current_test_id", newId); + return newId; + } + + + /** + * 生成下一个保存数据的Id + *

+ * 考虑到测试Id保存的的上线是1000 000,循环利用ID,超过后复写以前的数据 + */ + public static long generateNextTestId(int idHigh1, byte idHigh2, byte idHigh3, byte idHigh4) { + if (sContext == null) { + return -1; + } + long newId = generateNextTestId(); + TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); + testRecordsTotal.id = newId; + testRecordsTotal.botelv = sbotelv; + Log.d(logTag, "generateNextTestId [idHigh1, idHigh2, idHigh3, idHigh4]:" + newId); + KJDB.getDefaultInstance().save(testRecordsTotal); + if (mSensor == null) { + mSensor = new Sensor(); + } + int[] values = ProtoUtils.getSensorNumber(idHigh1, idHigh2, idHigh3, idHigh4); + mSensor.sensor_id = values[1]; + return newId; + } + + public static void genItem(int sensorId) { + if (sContext == null) { + return; + } + long newId = generateNextTestId(); + TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); + testRecordsTotal.id = newId; + testRecordsTotal.botelv = sbotelv; + Log.d(logTag, "generateNextTestId [idHigh1, idHigh2, idHigh3, idHigh4]:" + newId); + KJDB.getDefaultInstance().save(testRecordsTotal); + if (mSensor == null) { + mSensor = new Sensor(); + } + mSensor.sensor_id = sensorId; + } + + public static void genItem(int sensorId, String baudRate) { + if (sContext == null) { + return; + } + long newId = generateNextTestId(); + TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); + testRecordsTotal.id = newId; + testRecordsTotal.botelv = baudRate; + Log.d(logTag, "generateNextTestId [idHigh1, idHigh2, idHigh3, idHigh4]:" + newId); + KJDB.getDefaultInstance().save(testRecordsTotal); + if (mSensor == null) { + mSensor = new Sensor(); + } + mSensor.sensor_id = sensorId; + } + + static String sbotelv = "38400"; + + public static void mateSuccess(String botelv) { + sbotelv = botelv; + } + + public static long getCurrentTestId() { + if (sContext == null) { + return -1; + } + return SPUtils.getInstance(sContext).get("current_test_id", -1l); + } + + public static TestRecordsTotal getCurrentTestRecordsTotal() { + if (sContext == null) { + return null; + } + long id = getCurrentTestId(); + if (id == -1) { + return null; + } + return KJDB.getDefaultInstance().findById(id, TestRecordsTotal.class); + } + + public static void saveEggID(String eggNumber) { + /*TestRecordsTotal testRecordsTotal = getCurrentTestRecordsTotal(); + testRecordsTotal.egg_id = eggNumber; + KJDB.getDefaultInstance().update(testRecordsTotal);*/ + + mSensor.egg_id = eggNumber; + } + + public static void saveEggType(String eggType) { + /*TestRecordsTotal testRecordsTotal = getCurrentTestRecordsTotal(); + testRecordsTotal.egg_type = eggtype; + KJDB.getDefaultInstance().update(testRecordsTotal);*/ + + mSensor.egg_type = eggType; + } + + public static void saveConeNo(String coneNo) { + /*TestRecordsTotal testRecordsTotal = getCurrentTestRecordsTotal(); + testRecordsTotal.tupe_id = coneNumber; + KJDB.getDefaultInstance().update(testRecordsTotal);*/ + + mSensor.tupe_id = coneNo; + } + + public static void saveConeUsedTimes(String usedTimes) { + TestRecordsTotal testRecordsTotal = getCurrentTestRecordsTotal(); + testRecordsTotal.tupe_use_times = usedTimes; + mSensor.tv_tupe_use_times = usedTimes; + KJDB.getDefaultInstance().update(testRecordsTotal); + } + + private static SparseArray sItemSparseArray = new SparseArray<>(); + + public static void save(float value, int type) { + Item i = sItemSparseArray.get(type); + if (i != null) { + i.count++; + i.sum += value; + i.average = i.sum / i.count; + } else { + Item item = new Item(); + item.count = 1; + item.sum = value; + + item.average = value; + sItemSparseArray.put(type, item); + } + } + + public static class Item { + int count = 0; + float sum = 0; + float average = 0; + } + + public static void endTest(boolean save) { + if (save) { + endTest(); + } else { + NextTestIdCC(); + //清楚所有单条记录 + sItemSparseArray.clear(); + sbotelv = ""; + } + } + + + /*结束本次测试*/ + public static void endTest() { + long id = getCurrentTestId(); + if (id < 0) { + return; + } + TestRecordsTotal testRecordsTotal = getCurrentTestRecordsTotal(); + if (testRecordsTotal == null) { + return; + } + /*温度*/ + float temp = -1000; + /*湿度*/ + float Hum = -1000; + /*内压*/ + float pressurein = -1000; + /*外压*/ + float pressureout = -1000; + /*压差*/ + float pressure_yacha = -1000; + /*湿度*/ + float Hum20 = -1000; + /*内压*/ + float pressurein20 = -1000; + Item iItem41 = sItemSparseArray.get(41); + if (iItem41 != null) { + temp = iItem41.average; + } + testRecordsTotal.temp = f(temp); + + Item iItem42 = sItemSparseArray.get(42); + if (iItem42 != null) { + pressurein = iItem42.average; + } + testRecordsTotal.pressurein = f(pressurein); + + Item iItem43 = sItemSparseArray.get(43); + if (iItem43 != null) { + Hum = iItem43.average; + } + testRecordsTotal.Hum = f(Hum); + + Item iItem44 = sItemSparseArray.get(44); + if (iItem44 != null) { + pressureout = iItem44.average; + } + testRecordsTotal.pressureout = f(pressureout); + Item iItem45 = sItemSparseArray.get(45); + if (iItem45 != null) { + pressure_yacha = iItem45.average; + } + testRecordsTotal.pressure_yacha = f(pressure_yacha); + + Item iItem46 = sItemSparseArray.get(46); + if (iItem46 != null) { + Hum20 = iItem46.average; + } + testRecordsTotal.Hum20 = f(Hum20); + + Item iItem47 = sItemSparseArray.get(47); + if (iItem47 != null) { + pressurein20 = iItem47.average; + } + testRecordsTotal.pressurein20 = f(pressurein20); + testRecordsTotal.end_time = System.currentTimeMillis(); + + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(testRecordsTotal.end_time); + long startDatT = calendar.get(Calendar.DAY_OF_YEAR) + calendar.get(Calendar.YEAR) * 1000; + testRecordsTotal.day_t = startDatT; + List listSensor = KJDB.getDefaultInstance().findAllByWhere(Sensor.class, + "sensor_id=" + mSensor.sensor_id); + if (listSensor != null && listSensor.size() > 0) { + mSensor.id = listSensor.get(0).id; + KJDB.getDefaultInstance().update(mSensor); + } else { + KJDB.getDefaultInstance().save(mSensor); + } + testRecordsTotal.sensor_id = mSensor.sensor_id; + //更新execl信息 + //mExeclMa.write(testRecordsTotal); + testRecordsTotal.tagBackup = 0; + KJDB.getDefaultInstance().update(testRecordsTotal); + //清楚所有单条记录 + sItemSparseArray.clear(); + sbotelv = ""; + } + + + private static float f(float f) { + DecimalFormat df = new DecimalFormat("0.0"); + String pressure1 = df.format(f); + try { + Float ff = Float.parseFloat(pressure1); + return ff; + } catch (NumberFormatException e) { + e.printStackTrace(); + } + return f; + } + + public interface ExportCallback { + void exportProgress(int counts, int remain); + + void finish(int counts, int remain); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/PixelUtils.java b/app/src/main/java/com/handset/serialportsensor/utils/PixelUtils.java new file mode 100644 index 0000000..90ac120 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/PixelUtils.java @@ -0,0 +1,25 @@ +package com.handset.serialportsensor.utils; + +import android.content.Context; + +public class PixelUtils { + public static int px2sp(Context context, float pxValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (pxValue / fontScale + 0.5f); + } + + public static int sp2px(Context context, float spValue) { + final float fontScale =context.getResources().getDisplayMetrics().scaledDensity; + return (int) (spValue * fontScale + 0.5f); + } + + public static int dp2px(Context context, float dipValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dipValue * scale + 0.5f); + } + + public static int px2dp(Context context, float dipValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dipValue / scale + 0.5f); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/ProtoUtils.java b/app/src/main/java/com/handset/serialportsensor/utils/ProtoUtils.java new file mode 100644 index 0000000..13449a9 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/ProtoUtils.java @@ -0,0 +1,105 @@ +package com.handset.serialportsensor.utils; + +import com.handset.serialportsensor.constant.Constant; + +public class ProtoUtils { + + public static final int HEADER_BYTE_NUM = 2; + + public static final int ID_BYTE_NUM = 4; + + public static final int COMMAND_BYTE_NUM = 2; + + private static final int MAX_MANUFACTURER_NO = 2; + + private static final int MIN_MANUFACTURER_NO = 0; + + public static final int MAX_MANUFACTURER_INTERNAL_NO = 999; + + private static final int MIN_MANUFACTURER_INTERNAL_NO = 1; + + public static int getCommandValue(int[] values) { + return (values[1] >> 8); + } + + public static byte getIdHigh1(int[] values) { + return (byte) ((values[0] >> 24) & 0xFF); + } + + public static byte getIdHigh2(int[] values) { + return (byte) ((values[0] >> 16) & 0xFF); + } + + public static byte getIdHigh3(int[] values) { + return (byte) ((values[0] >> 8) & 0xFF); + } + + public static byte getIdHigh4(int[] values) { + return (byte) (values[0] & 0xFF); + } + + public static byte getIdHigh1(int low) { + return (byte) ((low >> 24) & 0xFF); + } + + public static byte getIdHigh2(int low) { + return (byte) (low >> 16 & 0xFF); + } + + public static byte getIdHigh3(int high) { + return (byte) ((high >> 8) & 0xFF); + } + + public static byte getIdHigh4(int high) { + return (byte) (high & 0xFF); + } + + public static byte[] getByte4Id(String id) { + byte year = (byte) Integer.parseInt(id.substring(0, 2)); + byte batch = (byte) Integer.parseInt(id.substring(2, 4)); + Integer num = Integer.parseInt(id.substring(4, 8)); + byte numHigh = (byte) (num >> 8 & 0xFF); + byte numLow = (byte) (num & 0xFF); + byte[] last = {year, batch, numHigh, numLow}; + return last; + } + + public static byte[] genSentCommand11Byte(byte command, byte idHigh1, byte idHigh2, byte idHigh3, byte idHigh4) { + byte[] bytes1 = {idHigh1, idHigh2, idHigh3, idHigh4, 0x00, command, 0x00}; + int crc1021 = CRC16Utils.getCRC1021(bytes1); + byte low = (byte) (crc1021 & 0xff); + byte high = (byte) ((crc1021 >> 8) & 0xff); + byte[] getIdBuffer = {(byte) 0xDD, (byte) 0xDD, idHigh1, idHigh2, idHigh3, idHigh4, 0x00, command, 0x00, low, high}; + return getIdBuffer; + } + + public static byte[] genSentCommandSetId(byte idHigh1, byte idHigh2, byte idHigh3, byte idHigh4, + byte nidHigh1, byte nidHigh2, byte nidHigh3, byte nidHigh4) { + byte[] bytes1 = {idHigh1, idHigh2, idHigh3, idHigh4, 0x00, Constant.Command.COMMAND_50, 0x04, nidHigh1, nidHigh2, nidHigh3, nidHigh4}; + int crc1021 = CRC16Utils.getCRC1021(bytes1); + byte low = (byte) (crc1021 & 0xff); + byte high = (byte) ((crc1021 >> 8) & 0xff); + byte[] getIdBuffer = {(byte) 0xDD, (byte) 0xDD, idHigh1, idHigh2, idHigh3, idHigh4, 0x00, Constant.Command.COMMAND_50, 0x04, + nidHigh1, nidHigh2, nidHigh3, nidHigh4, low, high}; + return getIdBuffer; + } + + public static int[] getNumber(byte idHigh1, byte idHigh2) { + int id = (idHigh2 << 8) + idHigh1; + int interId = id % 1000;//厂家内部ID(0x0041-0x2fff) 0x6042 + int number = id / 1000;//厂家编号(0-4) + if (interId >= MIN_MANUFACTURER_INTERNAL_NO) { + if (number >= MIN_MANUFACTURER_NO && number <= MAX_MANUFACTURER_NO) { + return new int[]{number, interId}; + } + } + return null; + } + + public static int[] getSensorNumber(int idHigh1, byte idHigh2, byte idHigh3, byte idHigh4) { + int mId = Utils.byteArray2Int(new byte[]{idHigh3, idHigh4}); + int id = (idHigh1 * 100 + idHigh2) * 10000 + mId; + int number = mId / 1000;//厂家编号(0-4) + return new int[]{number, id}; + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/SPUtils.java b/app/src/main/java/com/handset/serialportsensor/utils/SPUtils.java new file mode 100644 index 0000000..c56dd20 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/SPUtils.java @@ -0,0 +1,303 @@ +/* + ShengDao Android Client, PreferencesManager + Copyright (c) 2014 ShengDao Tech Company Limited + */ + +package com.handset.serialportsensor.utils; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.text.TextUtils; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Set; + +/** + * [PreferencesManager管理类,提供get和put方法来重写SharedPreferences所提供的方法,更为实用和便捷] + * + * @author huxinwu + * @version 1.0 + * @date 2014-3-5 + **/ +@SuppressWarnings("ALL") +public class SPUtils { + + private final String tag = SPUtils.class.getSimpleName(); + + private Context mContext; + private SharedPreferences preferences; + private String DATA_URL = "/data/data/"; + private String SHARED_PREFS = "/shared_prefs"; + + private static String shareName = "SHARE_DATA"; + public static final String THEME = "Theme"; + public static final String LANG = "Lang"; + + private static SPUtils instance; + + /** + * 构造方法 + * + * @param context + */ + private SPUtils(Context context) { + this(context, shareName); + } + + /** + * 构造方法 + * + * @param context + * @param shareName + */ + private SPUtils(Context context, String shareName) { + mContext = context; + preferences = context.getSharedPreferences(shareName, + Context.MODE_PRIVATE); + } + + /** + * 得到单例模式的PreferencesManager对象 + * + * @param context 上下文 + * @return + */ + public static SPUtils getInstance(Context context) { + return getInstance(context, shareName); + } + + /** + * 得到单例模式的PreferencesManager对象 + * + * @param context 上下文 + * @param shareName 文件名称 + * @return + */ + public static SPUtils getInstance(Context context, + String shareName) { + if (instance == null) { + synchronized (SPUtils.class) { + if (instance == null) { + instance = new SPUtils(context, shareName); + } + } + } + return instance; + } + + public void put(String key, boolean value) { + Editor edit = preferences.edit(); + if (edit != null) { + edit.putBoolean(key, value); + edit.commit(); + } + } + + + public void put(String key, String value) { + Editor edit = preferences.edit(); + if (edit != null) { + edit.putString(key, value); + edit.commit(); + } + } + + public void put(String key, int value) { + Editor edit = preferences.edit(); + if (edit != null) { + edit.putInt(key, value); + edit.commit(); + } + } + + public void put(String key, float value) { + Editor edit = preferences.edit(); + if (edit != null) { + edit.putFloat(key, value); + edit.commit(); + } + } + + public void put(String key, long value) { + Editor edit = preferences.edit(); + if (edit != null) { + edit.putLong(key, value); + edit.commit(); + } + } + + public void put(String key, Set value) { + Editor edit = preferences.edit(); + if (edit != null) { + edit.putStringSet(key, value); + edit.commit(); + } + } + + /** + * 直接存放对象,反射将根据对象的属性作为key,并将对应的值保存。 + * + * @param t + */ + @SuppressWarnings("rawtypes") + public void put(T t) { + try { + String methodName = ""; + String saveValue = ""; + String fieldName = ""; + Editor edit = preferences.edit(); + Class cls = t.getClass(); + + if (edit != null) { + + Method[] methods = cls.getDeclaredMethods(); + Field[] fields = cls.getDeclaredFields(); + + for (Method method : methods) { + methodName = method.getName(); + for (Field f : fields) { + fieldName = f.getName(); + if (methodName.toLowerCase().contains(fieldName.toLowerCase())) { + Object value = method.invoke(t); + if (value != null && !TextUtils.isEmpty(String.valueOf(value))) { + saveValue = String.valueOf(value); + } + edit.putString(fieldName, String.valueOf(saveValue)); + break; + } + } + } + edit.commit(); + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + + public String get(String key) { + return preferences.getString(key, ""); + } + + public String get(String key, String defValue) { + return preferences.getString(key, defValue); + } + + public boolean get(String key, boolean defValue) { + return preferences.getBoolean(key, defValue); + } + + public int get(String key, int defValue) { + return preferences.getInt(key, defValue); + } + + public float get(String key, float defValue) { + return preferences.getFloat(key, defValue); + } + + public long get(String key, long defValue) { + return preferences.getLong(key, defValue); + } + + public Set get(String key, Set defValue) { + return preferences.getStringSet(key, defValue); + } + + /** + * 获取整个对象,跟put(T t)对应使用, 利用反射得到对象的属性,然后从preferences获取 + * + * @param cls + * @return + */ + public T get(Class cls) { + T obj = null; + String fieldName = ""; + try { + obj = cls.newInstance(); + Field[] fields = cls.getDeclaredFields(); + for (Field f : fields) { + fieldName = f.getName(); + if (!"serialVersionUID".equals(fieldName)) { + f.setAccessible(true); + f.set(obj, get(f.getName())); + } + } + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + return obj; + } + + public int getTheme(int defThemeId) { + return instance.get(THEME, defThemeId); + } + + public void setTheme(int themeId) { + instance.put(THEME, themeId); + } + + public String getLanguage(String defLang) { + return instance.get(LANG, defLang); + } + + public void setLang(String Language) { + instance.put(LANG, Language); + } + + public void clearAll() { + try { + String fileName = shareName + ".xml"; + StringBuilder path = new StringBuilder(DATA_URL).append(mContext.getPackageName()).append(SHARED_PREFS); + File file = new File(path.toString(), fileName); + if (file.exists()) { + file.delete(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 将对象以 json字符串的形式存到share preference里 + * + * @param key + * @param objeat + */ + /*public void put(String key, Object objeat) { + + Gson gson = new Gson(); + String json = gson.toJson(objeat); + Editor edit = preferences.edit(); + if (edit != null) { + edit.putString(key, json); + edit.commit(); + } + }*/ + + /** + * 将json字符串转成对象返回 + * + * @param key + * @param cls + * @param + * @return + */ + /*public T get(String key, Class cls) { + //Slog.d("SmartHomePrefs", "setWatchesPhone "); + String json = preferences.getString(key, null); + Gson gson = new Gson(); + return gson.fromJson(json, cls); + }*/ + +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/Slog.java b/app/src/main/java/com/handset/serialportsensor/utils/Slog.java new file mode 100644 index 0000000..c539f2d --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/Slog.java @@ -0,0 +1,323 @@ +package com.handset.serialportsensor.utils; + +import android.app.Activity; +import android.content.Context; +import android.os.Environment; +import android.os.storage.StorageManager; +import android.util.Log; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +/** + * log 输出,保存。 + * Created by Jeremy on 2015-09-17. + */ +@SuppressWarnings("ALL") +public final class Slog { + + public static boolean DEBUG = true; + + public static boolean SHOW_ACTIVITY_STATE = true; + + private static String LOG_FILE_FIRST_NAME = "com_htjc_sensor_"; + private final static String LOG_FILE_END_NAME = "_log.txt"; + private static int sLogLevel = 5; + public static final int VERBOSE_L = 5; + public static final int DEBUG_L = 4; + public static final int INFO_L = 3; + public static final int WARN_L = 2; + public static final int ERROR_L = 1; + + private static int SDCARD_LOG_FILE_SAVE_NUM = 7;// sd卡中日志文件的最多保存个数 + private static final String ERROR_TYPE = "ERROR"; + private static final String WARN_TYPE = "WARNING"; + private static final String INFO_TYPE = "INFO"; + private static final String DEBUG_TYPE = "DEBUG"; + private static final String VERBOSE_TYPE = "VERBOSE"; + private static String sPath; + private static Context sContext; + private static boolean isSaveLog = false; + + public static void init(Context context) { + sContext = context; + LOG_FILE_FIRST_NAME = context.getPackageName().replace(".", "_") + "_"; + } + + /*use init(Context context) instead + * */ + @Deprecated + public static void init(Context context, String com, String pkgId) { + sContext = context; + LOG_FILE_FIRST_NAME = pkgId.replace(".", "_") + "_"; + } + + public static void setDebug(boolean debug, boolean showActivityStatus) { + DEBUG = debug; + SHOW_ACTIVITY_STATE = showActivityStatus; + } + + public static void enableSaveLog(boolean isSaveLog) { + Slog.isSaveLog = isSaveLog; + } + + public static String getLogPath() { + return getSavePath(); + } + + private Slog() { + } + + public static void i(String tag, String msg) { + if (DEBUG) { + Log.i(tag, msg); + send("i", tag, msg); + } + } + + public static void v(String tag, String msg) { + if (DEBUG) { + Log.v(tag, msg); + send("v", tag, msg); + } + } + + public static void d(String tag, String msg) { + if (DEBUG) { + Log.d(tag, msg); + send("d", tag, msg); + } + } + + public static void e(String tag, String msg) { + if (DEBUG) { + Log.e(tag, msg); + send("e", tag, msg); + } + } + + public static void save(String tag, String msg) { + if (DEBUG) { + Log.d(tag, msg); + saveOP("d", tag, msg); + } + } + + public static final void state(String packName, String state) { + if (SHOW_ACTIVITY_STATE) + Log.d(packName, state); + } + + public static void send(String e, String tag, String msg) { + if (!isSaveLog) { + return; + } + String logmsg = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + + " " + e + " " + tag + " " + msg + ""; + writeLogToFile(getLogPath(), e, tag, logmsg); + delFile(getLogPath()); + } + + + /** + * 保存操作日志的log + */ + public static void saveOP(String e, String tag, String msg) { + if (!isSaveLog) { + return; + } + String logmsg = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " " + msg + ""; + writeLogToFileOP(getSavePathOP(), e, tag, logmsg); + delFile(getSavePathOP()); + } + + /** + * 打开日志文件并写入日志 + * + * @return + **/ + private static void writeLogToFileOP(String path, String type, String tag, String text) {// 新建或打开日志文件 + + try { + String needWriteFile = new SimpleDateFormat("yyyy_MM_dd").format(new Date()); + File file = getFileOP(path, needWriteFile); + FileWriter filerWriter = new FileWriter(file, true);//后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖 + BufferedWriter bufWriter = new BufferedWriter(filerWriter); + String needWriteMessage = new String(text.getBytes(), "utf-8") + "\"\n" + "\n"; + bufWriter.write(needWriteMessage); + bufWriter.newLine(); + bufWriter.close(); + filerWriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 打开日志文件并写入日志 + * + * @return + **/ + private static void writeLogToFile(String path, String type, String tag, String text) {// 新建或打开日志文件 + + try { + String needWriteFile = new SimpleDateFormat("yyyy_MM_dd").format(new Date()); + File file = getFile(path, needWriteFile); + FileWriter filerWriter = new FileWriter(file, true);//后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖 + BufferedWriter bufWriter = new BufferedWriter(filerWriter); + String needWriteMessage = new String(text.getBytes(), "utf-8") + "\"\n" + "\n"; + bufWriter.write(needWriteMessage); + bufWriter.newLine(); + bufWriter.close(); + filerWriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + + /** + * 删除多余的日志文件,只保留SDCARD_LOG_FILE_SAVE_NUM个 + */ + public static void delFile(String path) {// 删除日志文件 + List files = getFileSort(path); + if (files != null) { + for (int i = 0; i < files.size(); i++) { + if (i >= SDCARD_LOG_FILE_SAVE_NUM && files.get(i).exists()) { + files.get(i).delete(); + } + } + } + } + + public static File getFile(String savepath, String time) { + File savePath = new File(savepath); + if (!savePath.exists()) { + savePath.mkdirs(); + } + File file = new File(savePath, LOG_FILE_FIRST_NAME + time + + LOG_FILE_END_NAME); + return file; + } + + public static File getFileOP(String savepath, String time) { + File savePath = new File(savepath); + if (!savePath.exists()) { + savePath.mkdirs(); + } + File file = new File(savePath, time + + LOG_FILE_END_NAME); + return file; + } + + /** + * 获取目录下所有文件 + * + * @param realpath + * @param files + * @return + */ + public static List getFiles(String realpath, List files) { + + File realFile = new File(realpath); + if (realFile.isDirectory()) { + File[] subfiles = realFile.listFiles(); + if (subfiles != null) { + for (File file : subfiles) { + if (file.isDirectory()) { + getFiles(file.getAbsolutePath(), files); + } else { + files.add(file); + } + } + } + } + return files; + } + + public static List getOperateLogFiles() { + return getFileSort(getSavePathOP()); + } + + /** + * 获取目录下所有文件(按时间倒序排序) + * + * @return + */ + public static List getFileSort(String savePath) { + File save = new File(savePath); + if (!save.exists()) { + return null; + } + List list = getFiles(savePath, new ArrayList()); + if (list != null && list.size() > 0) { + Collections.sort(list, new Comparator() { + @Override + public int compare(File file, File newFile) { + if (file.lastModified() > newFile.lastModified()) { + return -1; + } else if (file.lastModified() == newFile.lastModified()) { + return 0; + } else { + return 1; + } + } + }); + } + return list; + } + + public static String getSavePath() { + return Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + "htjc" + File.separator + "sensor" + File.separator + "applog/"; + } + + public static String getSavePathOP() { + return Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + "htjc" + File.separator + "sensor" + File.separator + "operatelog/"; + } + + public static class StorageList { + private Context mContext; + private StorageManager mStorageManager; + private Method mMethodGetPaths; + + public StorageList(Context context) { + mContext = context; + if (mContext != null) { + mStorageManager = (StorageManager) mContext + .getSystemService(Activity.STORAGE_SERVICE); + try { + mMethodGetPaths = mStorageManager.getClass() + .getMethod("getVolumePaths"); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + } + + public String[] getVolumePaths() { + String[] paths = null; + try { + paths = (String[]) mMethodGetPaths.invoke(mStorageManager); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + return paths; + } + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/SpUtil.java b/app/src/main/java/com/handset/serialportsensor/utils/SpUtil.java new file mode 100644 index 0000000..53cf4cb --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/SpUtil.java @@ -0,0 +1,159 @@ +package com.handset.serialportsensor.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; + +/** + * Created by yxm on 16-6-23. + */ +public class SpUtil { + /** + * 保存在手机里面的文件名 + */ + public static final String FILE_NAME = "share_data"; + + /** + * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法 + */ + public static void put(Context context, String key, Object object) { + put(context, FILE_NAME, key, object); + } + + public static void put(Context context, String spName, String key, Object object) { + SharedPreferences sp = context.getSharedPreferences(spName, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + if (object instanceof String) { + editor.putString(key, (String) object); + } else if (object instanceof Integer) { + editor.putInt(key, (Integer) object); + } else if (object instanceof Boolean) { + editor.putBoolean(key, (Boolean) object); + } else if (object instanceof Float) { + editor.putFloat(key, (Float) object); + } else if (object instanceof Long) { + editor.putLong(key, (Long) object); + } else { + editor.putString(key, object.toString()); + } + SharedPreferencesCompat.apply(editor); + } + + /** + * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值 + */ + public static Object get(Context context, String key, Object defaultObject) { + return get(context, FILE_NAME, key, defaultObject); + } + + public static Object get(Context context, String spName, String key, Object defaultObject) { + SharedPreferences sp = context.getSharedPreferences(spName, + Context.MODE_PRIVATE); + if (defaultObject instanceof String) { + return sp.getString(key, (String) defaultObject); + } else if (defaultObject instanceof Integer) { + return sp.getInt(key, (Integer) defaultObject); + } else if (defaultObject instanceof Boolean) { + return sp.getBoolean(key, (Boolean) defaultObject); + } else if (defaultObject instanceof Float) { + return sp.getFloat(key, (Float) defaultObject); + } else if (defaultObject instanceof Long) { + return sp.getLong(key, (Long) defaultObject); + } + return null; + } + + /** + * 移除某个key值已经对应的值 + */ + public static void remove(Context context, String key) { + remove(context, FILE_NAME, key); + } + + public static void remove(Context context, String spName, String key) { + SharedPreferences sp = context.getSharedPreferences(spName, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + editor.remove(key); + SharedPreferencesCompat.apply(editor); + } + + /** + * 清除所有数据 + */ + public static void clear(Context context) { + clear(context, FILE_NAME); + } + + public static void clear(Context context, String spName) { + SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + editor.clear(); + SharedPreferencesCompat.apply(editor); + } + + /** + * 查询某个key是否已经存在 + */ + public static boolean contains(Context context, String key) { + return contains(context, FILE_NAME, key); + } + + public static boolean contains(Context context, String spName, String key) { + SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE); + return sp.contains(key); + } + + /** + * 返回所有的键值对 + */ + public static Map getAll(Context context) { + return getAll(context, FILE_NAME); + } + + public static Map getAll(Context context, String spName) { + SharedPreferences sp = context.getSharedPreferences(spName, + Context.MODE_PRIVATE); + return sp.getAll(); + } + + /** + * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类 + */ + private static class SharedPreferencesCompat { + private static final Method sApplyMethod = findApplyMethod(); + + /** + * 反射查找apply的方法 + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + private static Method findApplyMethod() { + try { + Class clz = SharedPreferences.Editor.class; + return clz.getMethod("apply"); + } catch (NoSuchMethodException e) { + } + return null; + } + + /** + * 如果找到则使用apply执行,否则使用commit + */ + public static void apply(SharedPreferences.Editor editor) { + try { + if (sApplyMethod != null) { + sApplyMethod.invoke(editor); + return; + } + } catch (IllegalArgumentException e) { + } catch (IllegalAccessException e) { + } catch (InvocationTargetException e) { + } + editor.commit(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/handset/serialportsensor/utils/SplitUtils.java b/app/src/main/java/com/handset/serialportsensor/utils/SplitUtils.java new file mode 100644 index 0000000..20e46cf --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/SplitUtils.java @@ -0,0 +1,30 @@ +package com.handset.serialportsensor.utils; + +import android.util.Log; + +import com.google.common.base.Splitter; +import com.handset.serialportlib.ByteUtils; + +import java.util.Collections; + +public class SplitUtils { + private static final String logTag = "HANDSET-JE002-EX"; + + public static Iterable split(String raw) { + try { + if (raw.length() == 22) { + return Splitter.fixedLength(22).split(raw); + } else if (raw.length() == 28) { + return Splitter.fixedLength(28).split(raw); + } else if(raw.length() > 28){ + byte[] bytes = ByteUtils.hexStrToBytes(raw); + int len = bytes[8] & 0xff; + int resLen = 18 + len * 2 + 4; + Log.i(logTag, "split len: " + len + ", resLen: " + resLen); + return Splitter.fixedLength(resLen).split(raw); + } else return Collections.emptyList(); + } catch (Exception e) { + return Collections.emptyList(); + } + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/StatusBarUtils.java b/app/src/main/java/com/handset/serialportsensor/utils/StatusBarUtils.java new file mode 100644 index 0000000..f8c9e12 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/StatusBarUtils.java @@ -0,0 +1,36 @@ +package com.handset.serialportsensor.utils; + +import android.app.Activity; +import android.graphics.Color; +import android.os.Build; +import android.support.annotation.ColorRes; +import android.support.v4.content.ContextCompat; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +public class StatusBarUtils { + public static void setStatusColor(Activity activity, boolean isTranslate, boolean isDarkText, @ColorRes int bgColor) { + //如果系统为6.0及以上,就可以使用Android自带的方式 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Window window = activity.getWindow(); + View decorView = window.getDecorView(); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); //可有可无 + decorView.setSystemUiVisibility((isTranslate ? View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN : 0) | (isDarkText ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0)); + window.setStatusBarColor(isTranslate ? Color.TRANSPARENT : ContextCompat.getColor(activity, bgColor)); //Android5.0就可以用 + } + } + + public static void setTranslucentStatus(Activity activity) { + // 5.0以上系统状态栏透明 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Window window = activity.getWindow(); + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setStatusBarColor(Color.TRANSPARENT); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + } + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/ToastHelper.java b/app/src/main/java/com/handset/serialportsensor/utils/ToastHelper.java new file mode 100644 index 0000000..e1bca88 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/ToastHelper.java @@ -0,0 +1,169 @@ +package com.handset.serialportsensor.utils; + +import android.app.AlertDialog; +import android.text.TextUtils; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.view.animation.LinearInterpolator; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.activity.BaseActivity; + +public class ToastHelper { + public interface OnDialogClickListener { + void onOKClickListener(View view); + + void onCancelClickListener(View view); + } + + public interface OnDialogSubmitClickListener { + void onOKClickListener(View view); + } + + public static AlertDialog showSubmitDialog(final String title, int icon, String content, int btnBgColor, String ok, BaseActivity context, final OnDialogSubmitClickListener listener) { + AlertDialog dialog = showSubmitDialogNoShow(title, icon, content, btnBgColor, ok, context, listener); + context.showDialog(dialog); + return dialog; + } + + private static AlertDialog showSubmitDialogNoShow(final String title, int icon, String content, int btnBgColor, String ok, BaseActivity context, final OnDialogSubmitClickListener listener) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + View view = View.inflate(context, R.layout.dialog_btl_recognition_error, (null)); + final AlertDialog dialog = builder.create(); + dialog.setView(view); + TextView tvTitle = view.findViewById(R.id.tv_title); + tvTitle.setText(title); + ImageView ivImg = view.findViewById(R.id.iv_img); + ivImg.setImageResource(icon); + TextView tvContent = view.findViewById(R.id.tv_content); + tvContent.setText(content); + Button btnConfirm = view.findViewById(R.id.btn_confirm); + btnConfirm.setBackgroundColor(btnBgColor); + if (!TextUtils.isEmpty(ok)) { + btnConfirm.setText(ok); + } + btnConfirm.setOnClickListener((View view2) -> { + dialog.dismiss(); + listener.onOKClickListener(view2); + }); + return dialog; + } + + public static AlertDialog showChooseDialogNoShow(final String title, int icon, String content, int btnBgColor, String confirm, String cancel, BaseActivity context, final OnDialogClickListener listener) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + View view = View.inflate(context, R.layout.dialog_stop_test, (null)); + final AlertDialog dialog = builder.create(); + dialog.setView(view); + TextView tvTitle = view.findViewById(R.id.tv_title); + tvTitle.setText(title); + ImageView ivImg = view.findViewById(R.id.iv_img); + ivImg.setImageResource(icon); + TextView tvContent = view.findViewById(R.id.tv_content); + tvContent.setText(content); + Button btnConfirm = view.findViewById(R.id.btn_confirm); + btnConfirm.setBackgroundColor(btnBgColor); + if (!TextUtils.isEmpty(confirm)) { + btnConfirm.setText(confirm); + } + btnConfirm.setOnClickListener((View view2) -> { + dialog.dismiss(); + listener.onOKClickListener(view2); + }); + Button btnCancel = view.findViewById(R.id.btn_cancel); + if (!TextUtils.isEmpty(cancel)) { + btnCancel.setText(cancel); + } + btnCancel.setOnClickListener((View view3) -> { + dialog.dismiss(); + listener.onCancelClickListener(view3); + }); + return dialog; + } + + public static AlertDialog showTipDialog(BaseActivity context, int imgRes, int tips) { + return showTipDialog(context, imgRes, tips, (false)); + } + + public static AlertDialog showTipDialogAnimation(BaseActivity context, int imgRes, int tips) { + return showTipDialog(context, imgRes, tips, (true)); + } + + public static AlertDialog showTipDialogNoShow(BaseActivity context, int imgRes, int tips) { + return showTipDialogNoShow(context, imgRes, tips, (false)); + } + + private static AlertDialog showTipDialog(BaseActivity context, int imgRes, int tips, boolean showAnimation) { + AlertDialog dialog = showTipDialogNoShow(context, imgRes, tips, showAnimation); + context.showDialog(dialog); + return dialog; + } + + private static AlertDialog showTipDialogNoShow(BaseActivity context, int imgRes, int tips, boolean showAnimation) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + View view = View.inflate(context, R.layout.dialog_tips_layout, (null)); + final AlertDialog dialog = builder.create(); + if (dialog.getWindow() != null) { + dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent); + } + dialog.setView(view); + dialog.setCanceledOnTouchOutside(false); + dialog.setCancelable(false); + ImageView ivImg = view.findViewById(R.id.iv_loading); + if (imgRes != 0) { + ivImg.setVisibility(View.VISIBLE); + ivImg.setImageResource(imgRes); + } else { + ivImg.setVisibility(View.GONE); + } + if (showAnimation) { + Animation animation = AnimationUtils.loadAnimation(context, R.anim.rotate_anim); + animation.setInterpolator(new LinearInterpolator()); + ivImg.startAnimation(animation); + } + TextView tvTip = view.findViewById(R.id.tv_loading); + tvTip.setText(tips); + return dialog; + } + + public static void showResetSensorDialog(BaseActivity context, final OnDialogClickListener listener) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + View view = View.inflate(context, R.layout.dialog_chuchang, (null)); + final AlertDialog dialog = builder.create(); + dialog.setView(view); + Button btnCancel = view.findViewById(R.id.btn_cancel); + Button btnConfirm = view.findViewById(R.id.btn_confirm); + btnCancel.setOnClickListener((View view2) -> { + dialog.dismiss(); + listener.onCancelClickListener(view2); + }); + btnConfirm.setOnClickListener((View view3) -> { + dialog.dismiss(); + listener.onOKClickListener(view3); + + }); + context.showDialog(dialog); + } + + public static void showSaveSensorDialog(BaseActivity context, final OnDialogClickListener listener) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + View view = View.inflate(context, R.layout.dialog_save_alert, (null)); + final AlertDialog dialog = builder.create(); + dialog.setCancelable(false); + dialog.setView(view); + Button btnCancel = view.findViewById(R.id.btn_cancel); + Button btnConfirm = view.findViewById(R.id.btn_confirm); + btnCancel.setOnClickListener((View view2) -> { + dialog.dismiss(); + listener.onCancelClickListener(view2); + }); + btnConfirm.setOnClickListener((View view3) -> { + dialog.dismiss(); + listener.onOKClickListener(view3); + }); + context.showDialog(dialog); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/utils/Utils.java b/app/src/main/java/com/handset/serialportsensor/utils/Utils.java new file mode 100644 index 0000000..7752704 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/utils/Utils.java @@ -0,0 +1,203 @@ +package com.handset.serialportsensor.utils; + +import android.content.Context; +import android.util.Log; + +import java.io.File; +import java.io.FileOutputStream; +import java.math.BigInteger; + +public class Utils { + private static final String path = "/sys/class/peijian_dev/function/PeijianPowerEn"; + private static final String path1 = "/sys/class/peijian_dev/function/pogo_wake"; + + private final static String TAG = "Util"; + + public static void initBLNStatus(char status) { + setBLNStatus(status, path); + setBLNStatus(status, path1); + } + + private static void setBLNStatus(char status, String path) { + File file = new File(path); + FileOutputStream fos; + try { + if (!file.exists()) { + return; + } + fos = new FileOutputStream(file); + fos.write(status); + fos.close(); + } catch (Exception e) { + Log.e("setBLNStatus", "setBLNStatus error: ", e); + } + } + + //低位在前,高位在后 + public static byte[] intToByte(int num) { + byte[] bytes = new byte[4]; + bytes[0] = (byte) ((num >> 24) & 0xff); + bytes[1] = (byte) ((num >> 16) & 0xff); + bytes[2] = (byte) ((num >> 8) & 0xff); + bytes[3] = (byte) (num & 0xff); + return bytes; + } + + public static byte[] addBytes(byte[] data1, byte[] data2) { + byte[] data = new byte[data1.length + data2.length]; + System.arraycopy(data1, 0, data, 0, data1.length); + System.arraycopy(data2, 0, data, data1.length, data2.length); + return data; + } + + public static byte[] addCheckBytes(byte[] byteCommand, int data) { + byte[] bytes2 = Utils.intToByte(data);//data + byte[] bytes3 = Utils.addBytes(byteCommand, bytes2); + int crc1021Egg = CRC16Utils.getCRC1021(bytes3); + byte[] bytes4 = Utils.intToByte(crc1021Egg); + return Utils.addBytes(bytes3, bytes4); + } + + //根据ID获取厂家编号和厂家内部ID + public static int[] getNumber(int id) { + //id 厂家ID (number)*0x3000+(interId) + int b = 0x3000; + int low = 0x0041; + int high = 0x2fff; + int interId = id % b;//厂家内部ID(0x0041-0x2fff) 0x6042 + int number = id / b;//厂家编号(0-4) + if (interId >= low && interId <= high) { + if (number >= 0 && number <= 4) { + return new int[]{number, interId}; + } + } + return null; + } + + //低位在前,高位在后 + public static byte[] convertStringToHex(String str) { + char[] ch = str.toCharArray(); + byte[] hex = new byte[ch.length]; + for (int i = 0; i < ch.length; i++) { + hex[i] = (byte) ch[i]; + } + return hex; + } + + public static byte[] convertStringToHexDesc(String str) { + char[] ch = str.toCharArray(); + byte[] hex = new byte[ch.length]; + for (int i = 0; i < ch.length; i++) { + hex[i] = (byte) ch[ch.length - i - 1]; + } + return hex; + } + + public static String convertHexToString(String hex) { + StringBuilder sb = new StringBuilder(); + StringBuilder temp = new StringBuilder(); + for (int i = 0; i < hex.length() - 1; i += 2) { + //grab the hex in pairs + String output = hex.substring(i, (i + 2)); + //convert hex to decimal + int decimal = Integer.parseInt(output, 16); + //convert the decimal to character + sb.append((char) decimal); + temp.append(decimal); + } + + return sb.toString(); + } + + public static int dp2px(Context context, float dpValue) { + float scale = context.getResources().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } + + public static int sp2px(Context context, float spValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (spValue * fontScale + 0.5f); + } + + public static byte[] getCrcByte(byte[] command, String data) { + byte[] hex = Utils.convertStringToHex(data); + byte[] bytes2 = Utils.addBytes(command, hex); + int crc1021 = CRC16Utils.getCRC1021(bytes2); + byte low = (byte) (crc1021 & 0xff); + byte high = (byte) ((crc1021 >> 8) & 0xff); + byte[] getBaudBuffer = new byte[bytes2.length + 4]; + getBaudBuffer[0] = (byte) 0xDD; + getBaudBuffer[1] = (byte) 0xDD; + for (int i = 0; i < bytes2.length; i++) { + getBaudBuffer[i + 2] = bytes2[i]; + } + getBaudBuffer[getBaudBuffer.length - 2] = low; + getBaudBuffer[getBaudBuffer.length - 1] = high; + return getBaudBuffer; + } + + public static byte[] getCrcByte(byte[] command) { + int crc1021 = CRC16Utils.getCRC1021(command); + byte low = (byte) (crc1021 & 0xff); + byte high = (byte) ((crc1021 >> 8) & 0xff); + byte[] getBaudBuffer = new byte[command.length + 4]; + getBaudBuffer[0] = (byte) 0xDD; + getBaudBuffer[1] = (byte) 0xDD; + for (int i = 0; i < command.length; i++) { + getBaudBuffer[i + 2] = command[i]; + } + getBaudBuffer[getBaudBuffer.length - 2] = low; + getBaudBuffer[getBaudBuffer.length - 1] = high; + return getBaudBuffer; + } + + public static String byteArrayToString(byte[] b) { + StringBuilder hexBuilder = new StringBuilder(); + for (byte aB : b) { + String hexString = Integer.toHexString(aB & 0xFF); + if (hexString.length() < 2) { + hexBuilder.append(0); + } + hexBuilder.append(hexString); + } + BigInteger bigInteger = new BigInteger(hexBuilder.toString(), 16); + String s = bigInteger.toString(10); + return s; + } + + public final static int getInt(byte[] buf, boolean asc, int len) { + if (buf == null) { + throw new IllegalArgumentException("byte array is null!"); + } + if (len > 4) { + throw new IllegalArgumentException("byte array size > 4 !"); + } + int r = 0; + if (asc) + for (int i = len - 1; i >= 0; i--) { + r <<= 8; + r |= (buf[i] & 0x000000ff); + } + else + for (int i = 0; i < len; i++) { + r <<= 8; + r |= (buf[i] & 0x000000ff); + } + return r; + + } + + public final static int byteArray2Int(byte[] buf) { + return getInt(buf, false, 2); + } + + + public static String getSensorNoShow(String raw) { + if(raw.length() < 8) { + return raw; + } + StringBuilder sb = new StringBuilder(raw); + sb.deleteCharAt(4); + return sb.toString(); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/view/AutoLoadMoreListView.java b/app/src/main/java/com/handset/serialportsensor/view/AutoLoadMoreListView.java new file mode 100644 index 0000000..7da0333 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/view/AutoLoadMoreListView.java @@ -0,0 +1,169 @@ +package com.handset.serialportsensor.view; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AbsListView; +import android.widget.LinearLayout; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.TextView; + +import com.handset.serialportsensor.R; + +/** + * 目前很多App的ListView都有在分页显示时自动加载更多内容的功能,既: + * 1 每次只显示一页内容; + * 2 用户滚动到底部的时候,则会出现一行“正在加载”的提示并开始加载; + * 3 如果全部内容都加载完成了,则滚动到底部不会出现提示。 + *

+ * AutoLoadMoreListView在标准ListView的基础上,进行了简单的封装来实现这个功能; + * 1 “正在加载”的提示是一个footer,默认实现是文字加旋转动画; + * 2 可以指定footer的高度,背景颜色,文字等属性,也可以替换为自定义的layout; + * 3 footer是否显示由调用者决定; + * 4 当滚动到底部的时候,通过回调通知应用执行加载,加载完成后要告知加载完成; + */ +public class AutoLoadMoreListView extends ListView implements AbsListView.OnScrollListener { + + private View mLoadStatus; + private View mLoadMoreView; + //控制moreView的显示,是否显示是由调用者来决定的 + private boolean mShowLoadMore; + + private AutoLoadMoreListener mLoadMoreListener; + //是否正在执行加载更多的动作,防止重复调用 + private boolean mDoingLoadMore; + + + public AutoLoadMoreListView(Context context) { + super(context); + init(null, 0); + } + + public AutoLoadMoreListView(Context context, AttributeSet attrs) { + super(context, attrs); + init(attrs, 0); + } + + public AutoLoadMoreListView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(attrs, defStyle); + } + + private void init(AttributeSet attrs, int defStyle) { + mLoadMoreView = LayoutInflater.from(getContext()).inflate(R.layout.simple_auto_load_more, null); + mLoadStatus = LayoutInflater.from(getContext()).inflate(R.layout.simple_auto_load_more, null); + setOnScrollListener(this); + } + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + //检查是否要通知App去做加载更多 + if (mShowLoadMore && (!mDoingLoadMore) + && mLoadMoreListener != null + && (firstVisibleItem + visibleItemCount) >= totalItemCount) { + mDoingLoadMore = true; + mLoadMoreListener.onLoadMoreBegin(this); + } + } + + /** + * 设置是否显示“加载更多”footer + * + * @param show + */ + public void setShowLoadMore(boolean show) { + if (show == mShowLoadMore) { + return; + } + updateFoot(""); + mShowLoadMore = show; + + if (mShowLoadMore) { + this.addFooterView(mLoadMoreView); + } else { + this.removeFooterView(mLoadMoreView); + } + } + + public void setLoadMoreListener(AutoLoadMoreListener listener) { + mLoadMoreListener = listener; + } + + /** + * App设置是否加载更多动作已经完成 + * 只有本次加载完成了,当滚动到底部的时候,才能再次发起加载 + */ + public void loadMoreComplete() { + mDoingLoadMore = false; + updateFoot("数据已经全部加载"); + } + + /** + * 设置默认的加载更多footer的属性 + * + * @param height 高度 px + * @param bgColor 背景颜色 + * @param textSize 文字大小 sp + * @param textColor 文字颜色 + */ + public void setupDefaultLoadMoreView(int height, int bgColor, int textSize, int textColor) { + mLoadMoreView.setBackgroundColor(bgColor); + View v = mLoadMoreView.findViewById(R.id.auto_load_more_container); + LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) v + .getLayoutParams(); + lp.height = height; + v.setLayoutParams(lp); + + TextView textView = mLoadMoreView.findViewById(R.id.auto_load_more_text); + textView.setTextSize(textSize); + textView.setTextColor(textColor); + } + + boolean showFootStatus = false; + + public void updateFoot(String s) { + if (TextUtils.isEmpty(s)) { + if (showFootStatus) { + this.removeFooterView(mLoadStatus); + } + showFootStatus = false; + } else { + if (!showFootStatus) { + this.addFooterView(mLoadStatus); + } + TextView textView = mLoadStatus.findViewById(R.id.auto_load_more_text); + textView.setText(s); + showFootStatus = true; + } + } + + /** + * 设置自定义的加载更多footer + * + * @param view + */ + public void setCustomLoadMoreView(View view) { + mLoadMoreView = view; + } + + /** + * 在android4.2.2的机器上遇到一个问题,调用addFooterView的时候报 + * ListDataBindingAdapter cannot be cast to android.widget.HeaderViewListAdapter + * 在网上查找后得知,在Api18以下的机器,Wrapping做得不太好,可以用如下方法来规避。 + * + * @param adapter 适配器 + */ + @Override + public void setAdapter(ListAdapter adapter) { + this.addFooterView(mLoadMoreView); + super.setAdapter(adapter); + this.removeFooterView(mLoadMoreView); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/view/AutoLoadMoreListener.java b/app/src/main/java/com/handset/serialportsensor/view/AutoLoadMoreListener.java new file mode 100644 index 0000000..cc6ff21 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/view/AutoLoadMoreListener.java @@ -0,0 +1,9 @@ +package com.handset.serialportsensor.view; + +/** + * Created by LiGang on 2016/4/30. + */ +public interface AutoLoadMoreListener { + //通知App Listview已经滚动到底部,开始加载下一页数据 + void onLoadMoreBegin(final AutoLoadMoreListView listView); +} diff --git a/app/src/main/java/com/handset/serialportsensor/view/ExportProgressDialog.java b/app/src/main/java/com/handset/serialportsensor/view/ExportProgressDialog.java new file mode 100644 index 0000000..9aeeae0 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/view/ExportProgressDialog.java @@ -0,0 +1,61 @@ +package com.handset.serialportsensor.view; + +import android.app.Activity; +import android.app.AlertDialog; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.activity.BaseActivity; +import com.handset.serialportsensor.utils.ToastHelper; + +/** + * Created by zy on 2019/3/7. + */ + +public class ExportProgressDialog { + + private TextView tvContent; + private Button mButton; + public AlertDialog mAlertDialog; + + private String ss; + + public AlertDialog showExportDialogNoShow(BaseActivity context, final ToastHelper.OnDialogSubmitClickListener listener, int count, int remain, String ss, String title) { + this.ss = ss; + AlertDialog.Builder builder = new AlertDialog.Builder(context); + View view = View.inflate(context, R.layout.dialog_exporting_test_data, (null)); + mAlertDialog = builder.create(); + mAlertDialog.setView(view); + mAlertDialog.setCancelable(false); + tvContent = view.findViewById(R.id.content); + String text = (count == 0 && remain == 0) ? (ss + "······") : (ss + "(" + (count - remain) + "/" + count + ")······"); + tvContent.setText(text); + + ((TextView) (view.findViewById(R.id.title))).setText(title); + + mButton = view.findViewById(R.id.btn_confirm); + mButton.setOnClickListener((View view2) -> { + mAlertDialog.dismiss(); + listener.onOKClickListener(view2); + }); + return mAlertDialog; + } + + public boolean update(Activity activity, final int count, final int remain) { + if (mAlertDialog == null) { + return false; + } + activity.runOnUiThread(() -> { + if (tvContent != null) { + String text = ss + "(" + (count - remain) + "/" + count + ")······"; + tvContent.setText(text); + } + if (mButton != null) { + mButton.setText(remain == 0 ? R.string.finished : R.string.cancel); + } + }); + return true; + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/view/LinearLayoutManagerCus.java b/app/src/main/java/com/handset/serialportsensor/view/LinearLayoutManagerCus.java new file mode 100644 index 0000000..a585ee4 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/view/LinearLayoutManagerCus.java @@ -0,0 +1,26 @@ +package com.handset.serialportsensor.view; + +import android.content.Context; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.ViewGroup; + +/** + * Created by zy on 2019/2/27. + */ + +public class LinearLayoutManagerCus extends LinearLayoutManager { + public LinearLayoutManagerCus(Context context) { + super(context); + } + + @Override + public RecyclerView.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { + return super.generateLayoutParams(lp); + } + + @Override + public RecyclerView.LayoutParams generateDefaultLayoutParams() { + return new RecyclerView.LayoutParams((-1), (-2)); + } +} diff --git a/app/src/main/java/com/handset/serialportsensor/widget/DashBoard.java b/app/src/main/java/com/handset/serialportsensor/widget/DashBoard.java new file mode 100644 index 0000000..3432505 --- /dev/null +++ b/app/src/main/java/com/handset/serialportsensor/widget/DashBoard.java @@ -0,0 +1,379 @@ +package com.handset.serialportsensor.widget; + +import android.animation.ArgbEvaluator; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.text.TextPaint; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; + +import com.handset.serialportsensor.R; +import com.handset.serialportsensor.utils.PixelUtils; + +import java.math.BigDecimal; +import java.text.DecimalFormat; + +import static android.graphics.Paint.Style.STROKE; + +//@SuppressWarnings(value = "unused") +public class DashBoard extends View { + private static final String logTag = "HANDSET-JE002-EX"; + + private Paint paint; + //最外层圆环的颜色 + private int circleColor; + //圆环进度的颜色 + private int progressCircleColor; + + //圆环的厚度,即大小 + private float circleThickness; + //最上面字体的颜色 + //private int topTextColor; + //第二行字体的颜色 + private int secondTextColor; + //第三行字体的颜色 + private int thirdTextColor; + + //RoundProgress开始的颜色,决定RoundProgress的渐变区间 + private int progressStartColor; + //RoundProgress结束的颜色,决定RoundProgress的渐变区间 + private int ProgressEndColor; + //进度的最大值,默认是1000 + private double maxProgress; + //当前的进度,默认0 + private double currentProgress; + //第二行字 + private String secondText; + //第三行字 + private String thirdText = "kg"; + //最上面的字的大小 + //private float topTextSize; + //第二行字的大小 + private float secondTextSize; + //第三行字的大小 + private float thirdTextSize; + //最外层圆的半径 + private int outerFirstCircleRadius; + + + //文字颜色是否argb变化 + private boolean progressArgbColor; + + //小圆是否可用 + private boolean smallCircleEnable; + + private boolean customArc; + + private int startArc; + private int center; + + private Float valueFloor; + private Float valueCeiling; + + private int textPaintStroke; + private ArgbEvaluator mArgbEvaluator; + + private boolean showOutText; + protected Paint textStartPaint = new TextPaint(); + protected Paint textEndPaint = new TextPaint(); + protected RectF ringRect = new RectF(); + private float textStartSize; + private float textEndSize; + public String textStart; + public String textEnd; + private int textStartColor; + private int textEndColor; + private Context context; + private int circlePadding; + + public DashBoard(Context context) { + this(context, (null)); + this.context = context; + } + + public DashBoard(Context context, AttributeSet attrs) { + this(context, attrs, (0)); + this.context = context; + } + + public DashBoard(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + this.context = context; + paint = new Paint(); + + mArgbEvaluator = new ArgbEvaluator(); + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DashBoard); + + //获取自定义属性和默认值 + circleColor = typedArray.getColor(R.styleable.DashBoard_circleColor, context.getResources().getColor(R.color.dashboard_gray)); + + progressCircleColor = typedArray.getColor(R.styleable.DashBoard_progressCircleColor, context.getResources().getColor(R.color.dashboard_normal_end)); + + progressStartColor = typedArray.getColor(R.styleable.DashBoard_progressStartColor, getResources().getColor(R.color.dashboard_normal_start)); + ProgressEndColor = typedArray.getColor(R.styleable.DashBoard_progressEndColor, getResources().getColor(R.color.dashboard_normal_end)); + + circleThickness = typedArray.getDimension(R.styleable.DashBoard_circleThickness, PixelUtils.dp2px(context, 10)); + + secondTextColor = typedArray.getColor(R.styleable.DashBoard_secondTextColor, Color.BLACK); + thirdTextColor = typedArray.getColor(R.styleable.DashBoard_thirdTextColor, Color.BLACK); + secondText = typedArray.getString(R.styleable.DashBoard_secondText); + + maxProgress = typedArray.getInt(R.styleable.DashBoard_maxProgress, 100); + currentProgress = typedArray.getInt(R.styleable.DashBoard_currentProgress, 0); + customArc = typedArray.getBoolean(R.styleable.DashBoard_customArc, false); + startArc = typedArray.getInt(R.styleable.DashBoard_startArc, 0); + showOutText = typedArray.getBoolean(R.styleable.DashBoard_showOutText, false); + textStartSize = typedArray.getDimension(R.styleable.DashBoard_textStartSize, PixelUtils.sp2px(context, 10)); + textEndSize = typedArray.getDimension(R.styleable.DashBoard_textEndSize, PixelUtils.sp2px(context, 10)); + textStartColor = typedArray.getColor(R.styleable.DashBoard_textStartColor, context.getResources().getColor(R.color.dashboard_normal_end)); + textEndColor = typedArray.getColor(R.styleable.DashBoard_textEndColor, context.getResources().getColor(R.color.dashboard_normal_end)); + textStart = typedArray.getString(R.styleable.DashBoard_textStart); + textEnd = typedArray.getString(R.styleable.DashBoard_textEnd); + + valueFloor = typedArray.getFloat(R.styleable.DashBoard_valueFloor, (0.0f)); + valueCeiling = typedArray.getFloat(R.styleable.DashBoard_valueCeiling, (0.0f)); + + //设置第三行文字的默认文字 + String defaultThirdText = typedArray.getString(R.styleable.DashBoard_thirdText); + if (defaultThirdText != null) { + thirdText = defaultThirdText; + } + secondTextSize = typedArray.getDimension(R.styleable.DashBoard_secondTextSize, PixelUtils.sp2px(context, 45)); + thirdTextSize = typedArray.getDimension(R.styleable.DashBoard_thirdTextSize, PixelUtils.sp2px(context, 16)); + + //控制颜色渐变的开关 + progressArgbColor = typedArray.getBoolean(R.styleable.DashBoard_progressArgbColor, false); + smallCircleEnable = typedArray.getBoolean(R.styleable.DashBoard_smallCircleEnable, true); + typedArray.recycle(); + circlePadding = PixelUtils.dp2px(context, 18); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + int width = getWidth(); + int height = getHeight(); + + //第1步:画出最外层的圆环 + drawOuterFirstCircle(canvas); + + //第2步,画出圆弧 + drawArc(canvas); + + //第3步,画出三行文字 + drawText(canvas); + + if (showOutText) { + textStartPaint.setColor(textStartColor); + textStartPaint.setTextSize(textStartSize); + textStartPaint.setAntiAlias(true); + + textEndPaint.setColor(textEndColor); + textEndPaint.setTextSize(textEndSize); + textEndPaint.setAntiAlias(true); + } + + float delta = circleThickness; + int padding = PixelUtils.dp2px(getContext(), 10); + ringRect.set(delta + padding, + delta + padding, + width - delta - padding, + height - delta - padding); + float ringWidth = ringRect.right - ringRect.left; + //第5步,画出外面的文字 + if (showOutText && !TextUtils.isEmpty(textStart) && !TextUtils.isEmpty(textEnd)) { + int endArc = startArc + (int) currentProgress; + int startPadding = (int) textStartPaint.measureText(textEnd) / 2 + PixelUtils.dp2px(getContext(), 6); + if (startArc <= 0 || startArc >= 180) { + startPadding = 0; + } + int endPadding = (int) textEndPaint.measureText(textStart) / 3 + PixelUtils.dp2px(getContext(), 2); + if (endArc > 180) { + endPadding = 0 - endPadding; + } + canvas.drawText(textStart, ringWidth / 2.0f + (ringWidth - circlePadding) / 2 * sin(endArc) + endPadding, ringRect.top + ringWidth / 2 - ringWidth / 2 * cos(endArc), textStartPaint); + canvas.drawText(textEnd, ringWidth / 2.0f + (ringWidth - circlePadding) / 2 * sin(startArc) + startPadding, ringRect.top + ringWidth / 2 - ringWidth / 2 * cos(startArc), textEndPaint); + } + } + + /** + * 绘制最外层的圆 + * + * @param canvas 画笔 + */ + private void drawOuterFirstCircle(Canvas canvas) { + //设置圆的颜色 + paint.setColor(circleColor); + + //设置只绘制边框 + paint.setStyle(STROKE); + //设置圆的宽度 + paint.setStrokeWidth(circleThickness / 2); + //消除锯齿 + paint.setAntiAlias(true); + //画出圆 + canvas.drawCircle(center, center, outerFirstCircleRadius, paint); + } + + private void drawText(Canvas canvas) { + paint.setStrokeWidth(textPaintStroke); + paint.setStyle(Paint.Style.FILL); + + //画出第二行文本 + paint.setTextSize(secondTextSize); + paint.setColor(secondTextColor); + float textWidth2 = paint.measureText(secondText); + canvas.drawText(secondText, center - textWidth2 / 2, center - secondTextSize / 4, paint); //画出卡路里数值 + + //画出第三行文本 + paint.setTextSize(thirdTextSize); + paint.setColor(thirdTextColor); + if (thirdText != null) { + float textWidth3 = paint.measureText(thirdText); + canvas.drawText(thirdText, center - textWidth3 / 2, center + (float) outerFirstCircleRadius / 4 + thirdTextSize / 2, paint); //画出卡路里单位 + } + + } + + private void drawArc(Canvas canvas) { + paint.setStrokeWidth(circleColor); + + paint.setStyle(STROKE); + if (smallCircleEnable) { + paint.setStrokeCap(Paint.Cap.BUTT); + } else { + paint.setStrokeCap(Paint.Cap.ROUND); + } + paint.setAntiAlias(true); + + //设置圆弧宽度 + paint.setStrokeWidth(circleThickness + 1); + + RectF oval2 = new RectF(center - outerFirstCircleRadius, center - outerFirstCircleRadius, center + outerFirstCircleRadius, center + outerFirstCircleRadius); //用于定义的圆弧的形状和大小的界限 + + double progress; + //这里画圆环的时候第二个参数为开始角度,0表示右边中线,90表示底部,-outerFirstCircleRadius + if (currentProgress < maxProgress) { + progress = currentProgress; + drawArcByColor(canvas, oval2, progress); + } else { + progress = maxProgress; + drawArcByColor(canvas, oval2, progress); + } + } + + private void drawArcByColor(Canvas canvas, RectF oval2, double progress) { + for (int i = 0; i < progress / maxProgress * 360; i++) { + if (progressArgbColor) {//如果颜色渐变, 则改变色值 + progressCircleColor = (Integer) mArgbEvaluator.evaluate(i / 360f, progressStartColor, ProgressEndColor);//颜色插值器(level 11以上才可以用) + secondTextColor = ProgressEndColor; + } + paint.setAntiAlias(true); + paint.setColor(progressCircleColor); + if (customArc) { + if (i < maxProgress * 360) { + canvas.drawArc(oval2, (float) (-90 + i + startArc), 1.35f, false, paint); + } + } else { + if (i < maxProgress * 360) { + canvas.drawArc(oval2, (float) (-90 + i), 1.35f, false, paint); + } + } + } + } + + + /** + * 当控件的宽高发生变化的时候调用的方法 + * 在这里得到控件的宽高,避免在onDraw的时候多次初始化 + */ + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + //获取圆心的坐标,对于自身控件而言是1/2 + center = getMeasuredWidth() / 2; + //原本是半径是等于中心点,但是由于设置画笔宽度的时候,这个宽度会根据当前的半径,往外部和内部各扩展1/2。 + //所以在设置半径是需要减去圆环宽度的一半。 + //这里减去整个圆环厚度是因为想让圆环距离本控件有左右间距,故意为之 + outerFirstCircleRadius = (int) (center - circleThickness - PixelUtils.dp2px(context, 18)); + //文字不用太大 + textPaintStroke = 1; + } + + public float sin(int i) { + return (float) Math.sin(i * Math.PI / 180); + } + + public float cos(int i) { + return (float) Math.cos(i * Math.PI / 180); + } + + public void setTextStart(String textStart) { + this.textStart = textStart; + this.invalidate(); + } + + public void setTextEnd(String textEnd) { + this.textEnd = textEnd; + this.invalidate(); + } + + private final static String FLOAT_TYPE = "0.00"; + + public void setSecondText(Float value) { + BigDecimal tmp = new BigDecimal(value); + BigDecimal floor = new BigDecimal(valueFloor); + BigDecimal ceiling = new BigDecimal(valueCeiling); + if (!(tmp.compareTo(floor) < 0 || tmp.compareTo(ceiling) > 0)) { + this.secondText = new DecimalFormat(FLOAT_TYPE).format(value); + invalidate(); + return; + } + Log.w(logTag, ("item: " + thirdText + ", value: " + value + " exceed!")); + } + + public void setSecondText(Float value, boolean isNormal) { + Log.i(logTag, "value: " + value); + BigDecimal tmp = new BigDecimal(value); + BigDecimal floor = new BigDecimal(valueFloor); + BigDecimal ceiling = new BigDecimal(valueCeiling); + if (!(tmp.compareTo(floor) < 0 || tmp.compareTo(ceiling) > 0)) { + this.secondText = new DecimalFormat(FLOAT_TYPE).format(value); + setProgressStartColor(getResources().getColor(isNormal ? R.color.progress_normal_start : R.color.progress_err_end)); + setProgressEndColor(getResources().getColor(isNormal ? R.color.progress_normal_end : R.color.progress_err_end)); + invalidate(); + return; + } + Log.w(logTag, ("item: " + thirdText + ", value: " + value + " exceed!")); + } + + public void setSecondText(String value) { + this.secondText = value; + setProgressStartColor(getResources().getColor(R.color.progress_normal_start)); + setProgressEndColor(getResources().getColor( R.color.progress_normal_end )); + invalidate(); + } + + /** + * 控制RoundProgress颜色渐变 + * @param progressCircleColor startColor + */ + public void setProgressStartColor(int progressCircleColor) { + this.progressStartColor = progressCircleColor; + } + + /** + * 控制RoundProgress颜色渐变 + * @param progressCircleColor endColor + */ + public void setProgressEndColor(int progressCircleColor) { + this.ProgressEndColor = progressCircleColor; + } +} diff --git a/app/src/main/res/anim/rotate_anim.xml b/app/src/main/res/anim/rotate_anim.xml new file mode 100644 index 0000000..532f8ba --- /dev/null +++ b/app/src/main/res/anim/rotate_anim.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..aab6bf3 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable-xxhdpi/ic_launcher_c.png b/app/src/main/res/drawable-xxhdpi/ic_launcher_c.png new file mode 100644 index 0000000..be9ecf3 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_launcher_c.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon.png b/app/src/main/res/drawable-xxhdpi/icon.png new file mode 100644 index 0000000..31c4e57 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon.png differ diff --git a/app/src/main/res/drawable-xxhdpi/loading.png b/app/src/main/res/drawable-xxhdpi/loading.png new file mode 100644 index 0000000..a0a9143 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/loading.png differ diff --git a/app/src/main/res/drawable/background_red.xml b/app/src/main/res/drawable/background_red.xml new file mode 100644 index 0000000..9a5323a --- /dev/null +++ b/app/src/main/res/drawable/background_red.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_sharp.xml b/app/src/main/res/drawable/background_sharp.xml new file mode 100644 index 0000000..520a78d --- /dev/null +++ b/app/src/main/res/drawable/background_sharp.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_sharp_circle.xml b/app/src/main/res/drawable/background_sharp_circle.xml new file mode 100644 index 0000000..1ebf717 --- /dev/null +++ b/app/src/main/res/drawable/background_sharp_circle.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_toast.xml b/app/src/main/res/drawable/background_toast.xml new file mode 100644 index 0000000..e1e3447 --- /dev/null +++ b/app/src/main/res/drawable/background_toast.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_loading_dialog.xml b/app/src/main/res/drawable/bg_loading_dialog.xml new file mode 100644 index 0000000..f57d6da --- /dev/null +++ b/app/src/main/res/drawable/bg_loading_dialog.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_my_send.9.png b/app/src/main/res/drawable/bg_my_send.9.png new file mode 100644 index 0000000..c3af662 Binary files /dev/null and b/app/src/main/res/drawable/bg_my_send.9.png differ diff --git a/app/src/main/res/drawable/bg_read_btn_starting.xml b/app/src/main/res/drawable/bg_read_btn_starting.xml new file mode 100644 index 0000000..bf073bc --- /dev/null +++ b/app/src/main/res/drawable/bg_read_btn_starting.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_start_btn.xml b/app/src/main/res/drawable/bg_start_btn.xml new file mode 100644 index 0000000..39ec89c --- /dev/null +++ b/app/src/main/res/drawable/bg_start_btn.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_start_btn_new.xml b/app/src/main/res/drawable/bg_start_btn_new.xml new file mode 100644 index 0000000..edf02ca --- /dev/null +++ b/app/src/main/res/drawable/bg_start_btn_new.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stop_btn.xml b/app/src/main/res/drawable/bg_stop_btn.xml new file mode 100644 index 0000000..acb07f2 --- /dev/null +++ b/app/src/main/res/drawable/bg_stop_btn.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stop_btn_new.xml b/app/src/main/res/drawable/bg_stop_btn_new.xml new file mode 100644 index 0000000..1d8a230 --- /dev/null +++ b/app/src/main/res/drawable/bg_stop_btn_new.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/checkbox_style_abnormal.xml b/app/src/main/res/drawable/checkbox_style_abnormal.xml new file mode 100644 index 0000000..db486a0 --- /dev/null +++ b/app/src/main/res/drawable/checkbox_style_abnormal.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/src/main/res/drawable/checkbox_style_normal.xml b/app/src/main/res/drawable/checkbox_style_normal.xml new file mode 100644 index 0000000..feb20d1 --- /dev/null +++ b/app/src/main/res/drawable/checkbox_style_normal.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/src/main/res/drawable/chuanganqistate_background.xml b/app/src/main/res/drawable/chuanganqistate_background.xml new file mode 100644 index 0000000..11bbd82 --- /dev/null +++ b/app/src/main/res/drawable/chuanganqistate_background.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0c33ee7 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_msg_left.9.png b/app/src/main/res/drawable/ic_msg_left.9.png new file mode 100644 index 0000000..5eab4aa Binary files /dev/null and b/app/src/main/res/drawable/ic_msg_left.9.png differ diff --git a/app/src/main/res/drawable/ic_msg_right.9.png b/app/src/main/res/drawable/ic_msg_right.9.png new file mode 100644 index 0000000..cd61d07 Binary files /dev/null and b/app/src/main/res/drawable/ic_msg_right.9.png differ diff --git a/app/src/main/res/drawable/login_btn_bg.xml b/app/src/main/res/drawable/login_btn_bg.xml new file mode 100644 index 0000000..9bb67e8 --- /dev/null +++ b/app/src/main/res/drawable/login_btn_bg.xml @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/login_btn_bg_rc.xml b/app/src/main/res/drawable/login_btn_bg_rc.xml new file mode 100644 index 0000000..cae4e2f --- /dev/null +++ b/app/src/main/res/drawable/login_btn_bg_rc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/login_edittext_bg.xml b/app/src/main/res/drawable/login_edittext_bg.xml new file mode 100644 index 0000000..e2ba87d --- /dev/null +++ b/app/src/main/res/drawable/login_edittext_bg.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/logout_btn_bg.xml b/app/src/main/res/drawable/logout_btn_bg.xml new file mode 100644 index 0000000..94cc6ff --- /dev/null +++ b/app/src/main/res/drawable/logout_btn_bg.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/progressloading.xml b/app/src/main/res/drawable/progressloading.xml new file mode 100644 index 0000000..8216dc1 --- /dev/null +++ b/app/src/main/res/drawable/progressloading.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/seekbar_custom.xml b/app/src/main/res/drawable/seekbar_custom.xml new file mode 100644 index 0000000..a54fd08 --- /dev/null +++ b/app/src/main/res/drawable/seekbar_custom.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/seekbar_custom_blue.xml b/app/src/main/res/drawable/seekbar_custom_blue.xml new file mode 100644 index 0000000..91a70a9 --- /dev/null +++ b/app/src/main/res/drawable/seekbar_custom_blue.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/select_color.xml b/app/src/main/res/drawable/select_color.xml new file mode 100644 index 0000000..6393581 --- /dev/null +++ b/app/src/main/res/drawable/select_color.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_corner_bg.xml b/app/src/main/res/drawable/shape_corner_bg.xml new file mode 100644 index 0000000..0104444 --- /dev/null +++ b/app/src/main/res/drawable/shape_corner_bg.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_edit.xml b/app/src/main/res/drawable/shape_edit.xml new file mode 100644 index 0000000..e7f5464 --- /dev/null +++ b/app/src/main/res/drawable/shape_edit.xml @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_mate_bg.xml b/app/src/main/res/drawable/shape_mate_bg.xml new file mode 100644 index 0000000..e2ec680 --- /dev/null +++ b/app/src/main/res/drawable/shape_mate_bg.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_settings_corner_bg.xml b/app/src/main/res/drawable/shape_settings_corner_bg.xml new file mode 100644 index 0000000..db90201 --- /dev/null +++ b/app/src/main/res/drawable/shape_settings_corner_bg.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_status_green_round.xml b/app/src/main/res/drawable/shape_status_green_round.xml new file mode 100644 index 0000000..d156bba --- /dev/null +++ b/app/src/main/res/drawable/shape_status_green_round.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_status_grey_round.xml b/app/src/main/res/drawable/shape_status_grey_round.xml new file mode 100644 index 0000000..abc919e --- /dev/null +++ b/app/src/main/res/drawable/shape_status_grey_round.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_status_red_round.xml b/app/src/main/res/drawable/shape_status_red_round.xml new file mode 100644 index 0000000..b9d47db --- /dev/null +++ b/app/src/main/res/drawable/shape_status_red_round.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_store.xml b/app/src/main/res/drawable/shape_store.xml new file mode 100644 index 0000000..22cf2a2 --- /dev/null +++ b/app/src/main/res/drawable/shape_store.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/side_nav_bar.xml b/app/src/main/res/drawable/side_nav_bar.xml new file mode 100644 index 0000000..a73143e --- /dev/null +++ b/app/src/main/res/drawable/side_nav_bar.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/splash.xml b/app/src/main/res/drawable/splash.xml new file mode 100644 index 0000000..9243ede --- /dev/null +++ b/app/src/main/res/drawable/splash.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/text_color_conform_bg.xml b/app/src/main/res/drawable/text_color_conform_bg.xml new file mode 100644 index 0000000..13c7d0b --- /dev/null +++ b/app/src/main/res/drawable/text_color_conform_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/text_color_selector_abnormal.xml b/app/src/main/res/drawable/text_color_selector_abnormal.xml new file mode 100644 index 0000000..3340143 --- /dev/null +++ b/app/src/main/res/drawable/text_color_selector_abnormal.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/text_color_selector_normal.xml b/app/src/main/res/drawable/text_color_selector_normal.xml new file mode 100644 index 0000000..40e2d5f --- /dev/null +++ b/app/src/main/res/drawable/text_color_selector_normal.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/thumb.xml b/app/src/main/res/drawable/thumb.xml new file mode 100644 index 0000000..f5da12f --- /dev/null +++ b/app/src/main/res/drawable/thumb.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/thumb_blue.xml b/app/src/main/res/drawable/thumb_blue.xml new file mode 100644 index 0000000..32d53f3 --- /dev/null +++ b/app/src/main/res/drawable/thumb_blue.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_baudrate_setting.xml b/app/src/main/res/layout/activity_baudrate_setting.xml new file mode 100644 index 0000000..06e2eb3 --- /dev/null +++ b/app/src/main/res/layout/activity_baudrate_setting.xml @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_change_sensor_id_setings.xml b/app/src/main/res/layout/activity_change_sensor_id_setings.xml new file mode 100644 index 0000000..4b87c36 --- /dev/null +++ b/app/src/main/res/layout/activity_change_sensor_id_setings.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + +