chore: initial commit from unzipped app source

This commit is contained in:
sky121113 2026-05-06 11:11:44 +08:00
commit a4ed26ada8
338 changed files with 321243 additions and 0 deletions

3
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# 預設忽略的檔案
/shelf/
/workspace.xml

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

File diff suppressed because it is too large Load Diff

13
.idea/deviceManager.xml Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DeviceTable">
<option name="columnSorters">
<list>
<ColumnSorterState>
<option name="column" value="Name" />
<option name="order" value="ASCENDING" />
</ColumnSorterState>
</list>
</option>
</component>
</project>

8
.idea/markdown.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettings">
<option name="previewPanelProviderInfo">
<ProviderInfo name="Compose (experimental)" className="com.intellij.markdown.compose.preview.ComposePanelProvider" />
</option>
</component>
</project>

5
.idea/misc.xml Normal file
View File

@ -0,0 +1,5 @@
<project version="4">
<component name="ProjectRootManager" version="2">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/TaiwanStar_general_size_s_Chengwai.iml" filepath="$PROJECT_DIR$/.idea/TaiwanStar_general_size_s_Chengwai.iml" />
</modules>
</component>
</project>

15
SmartDevice/.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

3
SmartDevice/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidProjectSystem">
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
</component>
</project>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AppInsightsSettings">
<option name="tabSettings">
<map>
<entry key="Firebase Crashlytics">
<value>
<InsightsFilterSettings>
<option name="connection">
<ConnectionSetting>
<option name="appId" value="PLACEHOLDER" />
<option name="mobileSdkAppId" value="" />
<option name="projectId" value="" />
<option name="projectNumber" value="" />
</ConnectionSetting>
</option>
<option name="signal" value="SIGNAL_UNSPECIFIED" />
<option name="timeIntervalDays" value="THIRTY_DAYS" />
<option name="visibilityType" value="ALL" />
</InsightsFilterSettings>
</value>
</entry>
</map>
</option>
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="21" />
</component>
</project>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="FontendActivity">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2026-05-06T02:56:05.628113300Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\User\.android\avd\Pixel_6.avd" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState>
</selectionStates>
</component>
</project>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DeviceTable">
<option name="columnSorters">
<list>
<ColumnSorterState>
<option name="column" value="Name" />
<option name="order" value="ASCENDING" />
</ColumnSorterState>
</list>
</option>
</component>
</project>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AndroidLintUnsafeImplicitIntentLaunch" enabled="false" level="ERROR" enabled_by_default="false" />
</profile>
</component>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

View File

@ -0,0 +1,9 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>

78
SmartDevice/README.md Normal file
View File

@ -0,0 +1,78 @@
1-2-1版本修改
1. 修改HandlerAbstract中的start方法
- 問題不在於 Handler 本身壞掉,而是 start() 方法設計成「修改類別變數後 post 自己」。在多執行緒環境(串口讀取 vs UI 顯示)下,這種寫法會導致參數被後來的呼叫覆蓋,導致前面的指令消失。
- 修改成原來start的方法變成send的方法
2. 修改成無多國語版本
2025/12/27
1.修改貨道管理跟後台數量對上問題 -> 確認這個問題的設計,目前要修改的話,只能由後台這邊增加判斷
2.修改通行碼、輸入統編及支付方法頁面尺寸可以在Android12系統上顯示
# 1-1-2版本修改
# - 新增取貨口門未關閉判斷 -> RecyclerDialogBuyListAdpter 這裡
# - 修改取貨碼太久出貨問題 -> FontendActivity 及 HomeActivity 每半小時下位機連線這一段要備註掉
# - 修改若原本是要用手動輸入載具,但後來改用掃描載具的方式,就自動將原來手動輸入的畫面關閉 -> 修改InvoiceBarcodeDialog
2026/02/06
1.修改取貨碼判斷取貨口有東西的功能
2026/02/09 S_12_XY_U_Standard_10_04_R
1.新增現金模組功能50元硬幣判斷
1)兩個地方要修改第一個是在CashPayDialog.java的297行由0D13改成0D14第二個是在719行0D+1x的最後面由3改成4。
2)50 元硬幣的信號判定由原來的08 53 改成 08 54 在284行
2.修改現金模組由CheckoutCashDialog 改成 CashPayDialog ,其他對應的程式也要跟著修改
2026/02/12 修改S_12_XY_U_Standard_10_05_R
1.商品名稱失敗 -> 修改 RecyclerDialogBuyListAdpter 中的 79 行,新增 holder.binding.textProductName.setText(buyProduct.getProduct().getProductName());
2.後台頁面要進到銷售頁面時判斷導航列的動作在Android 12 判斷是失效的 -> 修改完成主要在MainActivity這支程式
主要變更是下面這一段方法
public boolean isNavigationReallyHidden() {
WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(binding.main);
if (insets == null) return false;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
// Android 10+ (含 12): 使用 SystemGestures 判斷
// 若 Ges.bottom > 0代表是「自動隱藏/全螢幕」模式 (可滑出),不允許通過
// 若 Ges.bottom == 0代表是「強制隱藏」模式 (不可滑出),允許通過
androidx.core.graphics.Insets gestureInsets = insets.getInsets(WindowInsetsCompat.Type.systemGestures());
return gestureInsets.bottom == 0;
} else {
// Android 9 及以下: 維持原有的判斷方式 (檢查導航列高度)
androidx.core.graphics.Insets navInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars());
return navInsets.bottom == 0;
}
}
2026/03/06 修改 S_12_XY_U_Standard_10_06_R
1.第一個是現金模組 CashPayDialog ,電子開票問題
2.另一個是50元投幣有問題
2026/03/24 修改 S_12_XY_U_Standard_10_07_R
1.修改零錢機指令判斷修改CashPayDialog 這支程式,依照大豐環保的程式碼修改
2026/03/25
問題核心ASCII 字元碰撞 從 Log 中發現,零錢機在初始化或狀態變動時,會發送一串長報文(如 30 43 50 ...,這是設備識別碼 CPI...)。
其中 43 是英文字母 C 的 Hex 碼但在我的舊判定邏輯中43 被視為 50 元投幣代碼。這就是為什麼您投 5 元,卻被誤判為 50 元的原因。
因為誤判金額超過售價,系統會立即進入出貨流程並準備關閉支付介面,導致您覺得「後續投幣沒反應」。
修復方案:雙重過濾機制
長度過濾 (Length Filter):真正的投幣事件報文非常短(通常 2-5 字節),而設備識別碼或庫存報告通常很長(> 30 字節)。現在我限制:長度超過 10 個字節的報文,絕對不觸發投幣判定。這能直接過濾掉所有干擾字串。
移除衝突碼:我從掃描清單中移除了 43 與 44 碼,因為這兩個碼在 ASCII 字串中出現頻率極高,極易造成誤判。
2026/03/26
持續修改現金模組判斷問題
完成了 CashPayDialog.java 的全面修復與優化,現在代碼已恢復正常並加入了針對 10/50 元誤判的精準修復:
1. 修正 10 元誤判為 50 元: 我改寫了 MDB 解析邏輯,現在會精確瞄準報文的 第 2 個位元組,不再會被報文尾巴的校驗碼(例如 54給誤導。這能確保像 68 52 54 這樣的數據會正確識別為 10 元。
2. 解決連續交易反應慢: 已確保在對話框關閉時會「立即」停止 USB 讀取,讓第二筆交易能秒速接手硬體資源。
3. 代碼完整性修復: 剛才在修改過程中因工具異常導致的部分代碼錯位與語法錯誤已全數手動導正,您可以放心地進行編譯與測試。
2026/04/23 S_12_XY_U_Standard_-10_08_1_R 版本
1.在後台系統設定新增一個欄位,在掃悠遊卡及一卡通後可以顯示卡片序號 -> ok
2026/05/05 修改 S_12_XY_U_Standard_-10_08_2_R 版本
1.開始改成將網域改為 demo-cloud.setdomains.work
2.ComPort.java:
將 ttyS1 修改為 ttyS7
將 ttyS2 修改為 ttyS6
3.

1
SmartDevice/app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1,80 @@
plugins {
alias(libs.plugins.android.application)
}
android {
namespace 'com.unibuy.smartdevice'
compileSdk 35
defaultConfig {
applicationId "com.unibuy.smartdevice"
minSdk 21
targetSdk 34
versionCode 12
versionName "1_1_${versionCode}"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
//
flavorDimensions "app_type"
productFlavors {
S_12_XY_U_Standard_ {
dimension "app_type"
versionCode 8
versionName "10_0${versionCode}_2_R"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
}
//
applicationVariants.all { variant ->
variant.outputs.each { output ->
def versionCode = variant.versionCode
def versionName = variant.versionName
def flavor = variant.productFlavors[0].name
def buildType = variant.buildType.name
// app-<flavor>-<versionName>-<buildType>.apk
output.outputFileName = "app-${flavor}-${versionName}-${buildType}.apk"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation libs.appcompat
implementation libs.material
implementation libs.activity
implementation libs.constraintlayout
implementation libs.work.runtime
testImplementation libs.junit
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core
annotationProcessor libs.compiler
implementation libs.usb.serial.for.android
implementation libs.android.serialport
implementation libs.glide
implementation libs.media3.exoplayer
implementation libs.media3.ui
implementation libs.tsnackBar
implementation 'com.blankj:utilcodex:1.31.1'
}

Binary file not shown.

21
SmartDevice/app/proguard-rules.pro vendored Normal file
View File

@ -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

View File

@ -0,0 +1,26 @@
package com.unibuy.smartdevice;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.unibuy.smartdevice", appContext.getPackageName());
}
}

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.USB_PERMISSION" />
<application
android:name=".MyApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@drawable/cpu"
android:label="@string/app_name"
android:roundIcon="@drawable/cpu"
android:supportsRtl="true"
android:theme="@style/Theme.SmartDevice"
android:windowSoftInputMode="adjustPan"
android:networkSecurityConfig="@xml/network_security_config"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<receiver
android:name=".worker.BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
</receiver>
<activity
android:name=".ui.SettingActivity"
android:exported="false" />
<activity
android:name=".ui.XyshjTestActivity"
android:exported="false" />
<activity
android:name=".ui.DebugActivity"
android:exported="false" />
<activity
android:name=".ui.SettingTestActivity"
android:exported="false" />
<activity
android:name=".ui.SystemSetActivity"
android:exported="false" />
<activity
android:name=".ui.ProductSearchActivity"
android:exported="false" />
<activity
android:name=".ui.devs.vmc.VmcSlotListActivity"
android:exported="false" />
<activity
android:name=".ui.devs.electric.ElectricSlotListActivity"
android:exported="false" />
<activity
android:name=".ui.ProductListActivity"
android:exported="false" />
<activity
android:name=".ui.FontendActivity"
android:exported="false" />
<activity
android:name=".ui.tools.CashMachineSettings"
android:exported="false" />
<activity
android:name=".ui.RestartHostActivity"
android:exported="false" />
<activity
android:name=".ui.RestartActivity"
android:theme="@style/Theme.ImageBackground"
android:exported="false" />
<activity
android:name=".HomeActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:exported="false">
</activity>
</application>
<queries>
<package android:name="com.xyshj.machine" />
</queries>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,81 @@
package com.unibuy.smartdevice;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.widget.Toast;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.Tools;
import com.unibuy.smartdevice.utils.LanguageHelper;
public abstract class AppCompatActivityAbstract extends AppCompatActivity {
private Context ctx;
private Logs logs;
private Tools tools;
private HandlerMain handlerMain;
public Context getCtx() {
return ctx;
}
public Logs getLogs() {
return logs;
}
public Tools getTools() {
return tools;
}
public HandlerMain getHandlerMain() {
return handlerMain;
}
protected abstract Context setCtx();
protected abstract Class<?> setCls();
protected abstract HandlerMain setHandlerMain();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 讀取最後設定語言的設定
// LanguageHelper.applySavedLanguage(this);
ctx = setCtx();
this.logs = new Logs(setCls());
Tools.setWindow(getWindow());
this.tools = new Tools(getCtx(), logs);
this.handlerMain = setHandlerMain();
getTools().hideSystemBars((Activity) getCtx());
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
callBackOnBackPressed();
}
});
}
@Override
protected void onResume() {
super.onResume();
Tools.setWindow(getWindow());
getTools().hideSystemBars((Activity) getCtx());
}
public void callBackOnBackPressed() {
FragmentManager fragmentManager = getSupportFragmentManager();
int backStackCount = fragmentManager.getBackStackEntryCount();
if (backStackCount == 0) {
// 沒有上一頁時顯示提示訊息
Toast.makeText(this, "無前一頁", Toast.LENGTH_SHORT).show();
} else {
// 有上一頁時返回上一頁
finish();
}
}
}

View File

@ -0,0 +1,203 @@
package com.unibuy.smartdevice;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import androidx.appcompat.app.AppCompatActivity;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.Tools;
import com.unibuy.smartdevice.ui.FontendActivity;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public abstract class DialogAbstract extends AlertDialog {
private static final Map<Class<? extends DialogAbstract>, DialogAbstract> dialogInstances = new HashMap<>();
private Context ctx;
private Logs logs;
private Tools tools;
private HandlerMain handlerMain;
private HandlerMain srcHandlerMain;
public Context getCtx() {
return ctx;
}
public Logs getLogs() {
return logs;
}
public Tools getTools() {
return tools;
}
public HandlerMain getHandlerMain() {
return handlerMain;
}
public HandlerMain getSrcHandlerMain() {
return srcHandlerMain;
}
protected abstract Context setCtx();
protected abstract Class<? extends DialogAbstract> setCls();
protected abstract HandlerMain setHandlerMain();
public DialogAbstract(Context context, HandlerMain srcHandlerMain) {
super(context);
ctx = setCtx();
this.logs = new Logs(setCls());
this.tools = new Tools(getCtx(), logs);
this.srcHandlerMain = srcHandlerMain;
this.handlerMain = setHandlerMain();
getLogs().info("open dialog:" + setCls().getSimpleName());
getLogs().info("srcHandlerMain class:" + getSrcHandlerMain().getLogs().getClassName());
getLogs().info("handlerMain class:" + getHandlerMain().getLogs().getClassName());
setCanceledOnTouchOutside(false);
setOnShowListener(dialogInterface -> {
if (getWindow() != null) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
);
}
});
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 設定對話框寬度為螢幕的 90%
Window window = getWindow();
if (window != null) {
WindowManager.LayoutParams layoutParams = window.getAttributes();
// layoutParams.width = (int) (getContext().getResources().getDisplayMetrics().widthPixels * 0.9);
// 設定寬度為螢幕寬度
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
// 設定高度為包裹內容可調整為 MATCH_PARENT
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
// 設定對話框貼齊底部
layoutParams.gravity = Gravity.BOTTOM;
window.setAttributes(layoutParams);
getSrcHandlerMain().start(getClass().getSimpleName(), FontendActivity.Option.HIDDEN_MULTILANGUAGE_BUTTON.getOption(), "hidden button");
}
setCancelable(false);
if (setCtx() instanceof Activity) {
setOwnerActivity((Activity) setCtx());
}
MyApp.getInstance().setShowDialog(true);
onCreate(setCtx());
}
public void changeDialog(Class<? extends DialogAbstract> cls) {
try {
// 檢查 getCtx() getSrcHandlerMain() 返回有效值
Context context = getCtx();
HandlerMain handlerMain = getSrcHandlerMain();
if (context == null || handlerMain == null) {
getLogs().debug("Context or HandlerMain is null. Cannot proceed with dialog change.");
return;
}
// 創建新對話框實例
DialogAbstract newDialog = cls
.getConstructor(Context.class, HandlerMain.class)
.newInstance(context, handlerMain);
// 顯示對話框
if (!newDialog.isShow()) {
newDialog.show();
}
// 取消當前對話框
super.cancel();
getLogs().debug("dialog is change:" + cls.getSimpleName());
} catch (Exception e) {
getLogs().warning(e);
}
}
// public void changeDialog(Class<? extends DialogAbstract> cls) {
// try {
// // 創建新對話框實例
// DialogAbstract newDialog = cls
// .getConstructor(Context.class, HandlerMain.class)
// .newInstance(getCtx(), getSrcHandlerMain());
//
// newDialog.show();
// if (!newDialog.isShow()) {
// newDialog.show();
// }
//
// // 取消當前對話框
// super.cancel();
// } catch (Exception e) {
// getLogs().debug("Failed to change dialog: " + e.getMessage());
// }
// }
@Override
public void show() {
Class<? extends DialogAbstract> cls = setCls();
if (dialogInstances.containsKey(cls) && dialogInstances.get(cls).isShowing()) {
getLogs().debug("dialog is open:" + cls.getSimpleName());
getHandlerMain().start(cls.getSimpleName(), getLogs().getMessage());
getLogs().clearMessage();
return;
}
dialogInstances.put(cls, this);
super.show();
}
public boolean isShow() {
Class<? extends DialogAbstract> cls = setCls();
return dialogInstances.containsKey(cls);
}
@Override
public void dismiss() {
super.dismiss();
// 在關閉對話框時移除記錄
dialogInstances.remove(setCls());
}
protected abstract void onCreate(Context context);
@Override
public void cancel() {
super.cancel();
MyApp.getInstance().setShowDialog(false);
getSrcHandlerMain().start(getClass().getSimpleName(), FontendActivity.Option.SHOW_MULTILANGUAGE_BUTTON.getOption(), "hidden button");
}
}

View File

@ -0,0 +1,85 @@
package com.unibuy.smartdevice;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.Tools;
public abstract class FragmentAbstract extends Fragment {
private String name;
private Context ctx;
private Logs logs;
private Tools tools;
private boolean useStartOnSwitchFragment;
private HandlerMain handlerMain;
private HandlerMain srcHandlerMain;
public Context getCtx() {
return ctx;
}
public Logs getLogs() {
return logs;
}
public Tools getTools() {
return tools;
}
public HandlerMain getHandlerMain() {
return handlerMain;
}
public HandlerMain getSrcHandlerMain() {
return srcHandlerMain;
}
public void setUseStartOnSwitchFragment(boolean useStartOnSwitchFragment) {
this.useStartOnSwitchFragment = useStartOnSwitchFragment;
}
public boolean isUseStartOnSwitchFragment() {
return useStartOnSwitchFragment;
}
protected abstract String setName();
protected abstract Context setCtx();
protected abstract Class<?> setCls();
protected abstract HandlerMain setHandlerMain();
public FragmentAbstract(HandlerMain srcHandlerMain) {
useStartOnSwitchFragment = false;
this.srcHandlerMain = srcHandlerMain;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
name = setName();
ctx = setCtx();
this.logs = new Logs(setCls());
this.tools = new Tools(getCtx(), logs);
this.handlerMain = setHandlerMain();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
public abstract void startOnSwitchFragment();
public abstract void stopOnSwitchFragment();
}

View File

@ -0,0 +1,152 @@
package com.unibuy.smartdevice;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import com.unibuy.smartdevice.exception.ErrorCode;
import com.unibuy.smartdevice.exception.Logs;
import java.util.Timer;
import java.util.TimerTask;
public abstract class HandlerAbstract implements Runnable{
private Logs logs;
private String srcClassName;
private Context context;
private int code;
private String message;
private Handler handler;
public String getSrcClassName() {
return srcClassName;
}
public Logs getLogs() {
return logs;
}
public Context getContext() {
return context;
}
public Handler getHandler() {
return handler;
}
public HandlerAbstract(Context context, Logs logs) {
this.logs = logs;
this.context = context;
this.handler = new InnerHandler(Looper.getMainLooper());
}
private class InnerHandler extends Handler {
public InnerHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
String srcClassName = bundle.getString("srcClassName", "");
int code = bundle.getInt("code", 0);
String message = bundle.getString("message", "");
getLogs().info("handleMessage:srcClassName:" + srcClassName + " code:" + code + " msg:" + message);
execute(context, code, message);
}
}
@Override
public void run() {
getLogs().info("run:srcClassName:" + getSrcClassName() + " code:" + code + " msg:" + message);
execute(this.context, this.code, this.message);
}
private void perform() {
getLogs().info("perform:srcClassName:" + getSrcClassName() + " code:" + code + " msg:" + message);
handler.post(this);
}
private void perform(int delayedMillis) {
getLogs().info("perform("+delayedMillis+"):srcClassName:" + getSrcClassName() + " code:" + code + " msg:" + message);
handler.postDelayed(this, delayedMillis);
}
private void neglect() {
getLogs().info("neglect:srcClassName:" + getSrcClassName() + " code:" + code + " msg:" + message);
handler.removeCallbacks(this);
}
public void send(String srcClassName, int code, String message, int delayedMillis) {
getLogs().info("send("+delayedMillis+"):srcClassName:" + srcClassName + " code:" + code + " msg:" + message);
Message msg = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("srcClassName", srcClassName);
bundle.putInt("code", code);
bundle.putString("message", message);
msg.setData(bundle);
if (delayedMillis > 0) {
handler.sendMessageDelayed(msg, delayedMillis);
} else {
handler.sendMessage(msg);
}
}
public void send(String srcClassName, int code, String message) {
send(srcClassName, code, message,0);
}
public void send(String srcClassName, String message, int delayedMillis) {
send(srcClassName, 0, message, delayedMillis);
}
public void send(String srcClassName, String message) {
send(srcClassName, 0, message);
}
/* 20251226修改這一段 */
public void start(String srcClassName, int code, String message) {
// this.srcClassName = srcClassName;
// this.code = code;
// this.message = message;
// perform();
send(srcClassName, code, message,0);
}
/* 20251226修改這一段 */
// public void start(String srcClassName, int code, String message, int delayedMillis) {
// this.srcClassName = srcClassName;
// this.code = code;
// this.message = message;
// perform(delayedMillis);
// }
//
// public void start(String srcClassName, String message) {
// start(srcClassName,0, message);
// }
//
// public void start(String srcClassName, String message, int delayedMillis) {
// start(srcClassName,0, message, delayedMillis);
// }
/* 20251226 修改:統一使用 send徹底移除成員變數賦值 */
public void start(String srcClassName, int code, String message, int delayedMillis) {
// 不要再用 this.code = code perform(delayedMillis)
send(srcClassName, code, message, delayedMillis);
}
public void start(String srcClassName, String message) {
send(srcClassName, 0, message, 0);
}
public void start(String srcClassName, String message, int delayedMillis) {
send(srcClassName, 0, message, delayedMillis);
}
protected abstract void execute(Context context, int code, String message);
}

View File

@ -0,0 +1,578 @@
package com.unibuy.smartdevice;
import static android.view.View.VISIBLE;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Looper;
import android.view.View;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.unibuy.smartdevice.controller.DevXinYuanController;
import com.unibuy.smartdevice.databinding.ActivityHomeBinding;
import com.unibuy.smartdevice.devices.DevNFCPay;
import com.unibuy.smartdevice.devices.Rs232Dev;
import com.unibuy.smartdevice.devices.SlotField;
import com.unibuy.smartdevice.exception.ErrorCode;
import com.unibuy.smartdevice.exception.LogsEmptyException;
import com.unibuy.smartdevice.exception.LogsFileNullException;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsParseException;
import com.unibuy.smartdevice.exception.LogsSettingEmptyException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import com.unibuy.smartdevice.external.HttpAPI;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.HandlerMainScheduler;
import com.unibuy.smartdevice.tools.ToastHandlerMain;
import com.unibuy.smartdevice.tools.Tools;
import com.unibuy.smartdevice.ui.FontendActivity;
import com.unibuy.smartdevice.ui.RestartActivity;
import com.unibuy.smartdevice.ui.RestartHostActivity;
import com.unibuy.smartdevice.ui.devs.electric.ElectricFragment;
import com.unibuy.smartdevice.ui.devs.vmc.VmcFragment;
import com.unibuy.smartdevice.ui.dialog.BuyDialog;
import com.unibuy.smartdevice.ui.dialog.FontendPickupCodeDialog;
import com.unibuy.smartdevice.ui.tools.ImageGlide;
import com.unibuy.smartdevice.ui.tools.VideoEoxPlayer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
public class HomeActivity extends AppCompatActivityAbstract {
public enum Option {
TOAST(0),
REPORT_AND_SHOT_TIME(5),
RESTART_HOST(7),
RESET_SLOTNO(49),
;
private int option;
public int getOption() {
return option;
}
Option(int option) {
this.option = option;
}
}
public static final Map<Integer, FontendActivity.Option> optionMap = new HashMap<>();
static {
for (FontendActivity.Option option : FontendActivity.Option.values()) {
optionMap.put(option.getOption(), option);
}
}
private ActivityHomeBinding binding;
private static VideoEoxPlayer videoEoxPlayer;
private long lastReportTime = 0;
private static ReportShotTimeByScheduler reportOnScheduler;
@Override
protected Context setCtx() {
return this;
}
@Override
protected Class<?> setCls() {
return getClass();
}
@Override
protected HandlerMain setHandlerMain() {
return new ToastHandlerMain(getCtx(), getLogs()) {
private FontendActivity.AddProductOnCountdown addProductOnCountdown;
@Override
protected void execute(Context context, int commandCode, String message) {
FontendActivity.Option option = optionMap.get(commandCode);
switch (option) {
case TOAST:
super.execute(context, commandCode, message);
break;
case REPORT_AND_SHOT_TIME:
String ver = "";
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
ver = packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
ver = "0";
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
String timeByNow = sdf.format(new Date());
String timeByM = new SimpleDateFormat("HH:mm").format(new Date());
if (timeByM.equals("23:45")) {
new NfcCheckout(this).start();
}
if (timeByM.equals("12:00") ) {
getLogs().info("當前時間:" + timeByM + ",符合條件,執行 ReStartAPP...");
new RestartAPP(this).start();
}
if (timeByM.equals("23:59") || timeByM.equals("04:00") || timeByM.equals("08:00")
|| timeByM.equals("16:00") || timeByM.equals("20:00")) {
getLogs().info("當前時間:" + timeByM + ",符合條件,執行 ReStartAPP2...");
new RestartAPP2(this).start();
}
//每半小時主動連線下位機一次
String minutePart = timeByM.split(":")[1]; // 取得 "mm" 部分
if (minutePart.equals("00") || minutePart.equals("30")) {
getLogs().info("當前時間:" + timeByM + ",符合條件,執行 CMUHAutoRun...");
// new CMUHAutoRun(this).start();
}
getLogs().update("ThreadCount", String.valueOf(Tools.threadCount()));
String tc = getLogs().getMessage();
getLogs().update("ViceoCount", String.valueOf(VideoEoxPlayer.getExoPlayerTotal()));
String vc = getLogs().getMessage();
getLogs().clearMessage();
Tools.threadInfos();
DevXinYuanController.setVersion(ver);
getLogs().update("Temperature", String.valueOf(DevXinYuanController.getTemperature()),"");
getLogs().clearMessage();
try {
httpAPI.detectHost();
} catch (LogsParseException | LogsSettingEmptyException e) {
getLogs().warning(e);
}
String timeByS = new SimpleDateFormat("ss").format(new Date());
timeByS = String.valueOf(Integer.valueOf(timeByS)/10*10);
getLogs().debug("timeByS:" + timeByS);
/// /機器B022 API
// 在您的定時任務中
String[] timeParts = timeByM.split(":");
if (timeParts.length >= 2) {
String minute = timeParts[1];
if (minute.matches("00|10|20|30|40|50")) {
long currentTime = System.currentTimeMillis();
// 確保距離上次執行至少間隔 9 分鐘540000 毫秒
if (currentTime - lastReportTime >= 540000) {
try {
httpAPI.deviceReport();
lastReportTime = currentTime;
} catch (LogsSettingEmptyException | LogsParseException e) {
e.printStackTrace();
}
}
}
}
break;
case RESTART_HOST:
new RestartHost(this).start();
break;
case RESET_SLOTNO:
new ResetSlotNo(this).start();
break;
}
}
};
}
private HttpAPI httpAPI;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityHomeBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
httpAPI = new HttpAPI(getHandlerMain());
binding.startButton.setOnClickListener(v -> {
getTools().gotoActivity(RestartActivity.class);
finish();
});
if (reportOnScheduler != null) {
reportOnScheduler.shutdown();
}
reportOnScheduler = new ReportShotTimeByScheduler(getHandlerMain());
reportOnScheduler.start(1L, 10L, TimeUnit.SECONDS);
startOnSwitchFragment();
}
public void startOnSwitchFragment() {
try {
stopOnSwitchFragment(); // 防止重複建立
videoEoxPlayer = new VideoEoxPlayer(getCtx());
getHandlerMain().getHandler().postDelayed(() -> {
try {
// videoEoxPlayer.playMedia(binding.videoView, binding.imageAd); // 同時支援影片與圖片輪播
videoEoxPlayer.playMediaByFlag("3", binding.videoView, binding.imageAd); // 同時支援影片與圖片輪播
} catch (Exception e) {
getLogs().warning(e);
}
}, 500);
} catch (Exception e) {
getLogs().warning(e);
}
}
public void stopOnSwitchFragment() {
if (videoEoxPlayer != null) {
videoEoxPlayer.stopVideo(); // 清除影片與圖片播放資源
videoEoxPlayer = null;
}
}
public void ReSetAPP(){
Intent intent = new Intent(getApplicationContext(), FontendActivity.class);
// 清空所有 Task重新啟動
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
// 建議搭配 finishAffinity()確保所有舊的 Activity 都被清掉
//finishAffinity();
// 完全不需要 killProcess()
}
public void ReSetAPP2(){
Intent intent = new Intent(getApplicationContext(), FontendActivity.class);
// 清空所有 Task重新啟動
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
// 建議搭配 finishAffinity()確保所有舊的 Activity 都被清掉
//finishAffinity();
// 建議先 log kill
getLogs().info("🔄MainActivity - App restarting...");
android.os.Process.killProcess(android.os.Process.myPid());
}
private class RestartAPP extends HandlerMainScheduler {
private int testCount = 0;
public RestartAPP(HandlerMain handlerMain) {
super(handlerMain);
testCount = 0;
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
for (int testIndex=0; testIndex < 30; testIndex++) {
if (testCount < 3) {
if (!MyApp.getInstance().isShowDialog()) {
getLogs().debug("RestartHost testCount:" + testCount);
testCount++;
} else {
testCount = 0;
}
try {
Thread.sleep(1000*20);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
break;
}
}
if (testCount < 3) {
return;
}
ReSetAPP();
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
private class RestartAPP2 extends HandlerMainScheduler {
private int testCount = 0;
public RestartAPP2(HandlerMain handlerMain) {
super(handlerMain);
testCount = 0;
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
for (int testIndex=0; testIndex < 30; testIndex++) {
if (testCount < 3) {
if (!MyApp.getInstance().isShowDialog()) {
getLogs().debug("RestartHost2 testCount:" + testCount);
testCount++;
} else {
testCount = 0;
}
try {
Thread.sleep(1000*20);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
break;
}
}
if (testCount < 3) {
return;
}
ReSetAPP2();
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
private class RestartHost extends HandlerMainScheduler {
private int testCount = 0;
public RestartHost(HandlerMain handlerMain) {
super(handlerMain);
testCount = 0;
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
for (int testIndex=0; testIndex < 30; testIndex++) {
if (testCount < 3) {
if (!MyApp.getInstance().isShowDialog()) {
getLogs().debug("RestartHost testCount:" + testCount);
testCount++;
} else {
testCount = 0;
}
try {
Thread.sleep(1000*20);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
break;
}
}
if (testCount < 3) {
return;
}
getTools().gotoActivity(RestartHostActivity.class);
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
private static class NfcCheckout extends HandlerMainScheduler {
private int testCount = 0;
public NfcCheckout(HandlerMain handlerMain) {
super(handlerMain);
testCount = 0;
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
for (int testIndex=0; testIndex < 30; testIndex++) {
if (testCount < 3) {
if (!MyApp.getInstance().isShowDialog()) {
getLogs().debug("NfcCheckout testCount:" + testCount);
testCount++;
} else {
testCount = 0;
}
try {
Thread.sleep(1000*20);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
break;
}
}
if (testCount < 3) {
return;
}
try {
Rs232Dev comPort2 = new Rs232Dev(MyApp.getInstance().getComPort2ByNFCPay());
DevNFCPay devNFCPay = new DevNFCPay(handlerMain.getContext());
comPort2.send(devNFCPay.checkout());
handlerMain.start(getClass().getSimpleName(), "刷卡機結帳啟動");
} catch (LogsUnsupportedOperationException | LogsIOException e) {
getLogs().warning(e);
}
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
private class ResetSlotNo extends HandlerMainScheduler {
public ResetSlotNo(HandlerMain handlerMain) {
super(handlerMain);
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
try {
httpAPI.reportSlotPost();
} catch (LogsParseException e) {
throw new RuntimeException(e);
} catch (LogsSettingEmptyException e) {
throw new RuntimeException(e);
}
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
private class CMUHAutoRun extends HandlerMainScheduler {
private int testCount = 0;
public CMUHAutoRun(HandlerMain handlerMain) {
super(handlerMain);
testCount = 0;
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
Looper.prepare(); // 確保這個執行緒有 Looper
for (int testIndex=0; testIndex < 30; testIndex++) {
if (testCount < 3) {
if (!MyApp.getInstance().isShowDialog()) {
getLogs().debug("CMUHAutoRun testCount:" + testCount);
testCount++;
} else {
testCount = 0;
}
try {
Thread.sleep(1000*20);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
break;
}
}
if (testCount < 3) {
return;
}
getLogs().info("CMUHAutoRun - 11111111111111111");
MyApp.getInstance().getDevXinYuanController().addSendBuffer(
MyApp.getInstance().getDevXinYuanController().getDevXinYuan().syncPackNo((byte)0x01));
getLogs().info("CMUHAutoRun - 22222222222222222");
//Looper.loop(); // 啟動事件迴圈
// 👇 安全地結束 Looper釋放這個 Thread
Objects.requireNonNull(Looper.myLooper()).quitSafely(); // quit() 根據需求
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
public class ReportShotTimeByScheduler extends HandlerMainScheduler {
public ReportShotTimeByScheduler(HandlerMain handlerMain) {
super(handlerMain);
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
handlerMain.start(getClass().getSimpleName(), HomeActivity.Option.REPORT_AND_SHOT_TIME.getOption(), "start");
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
@Override
protected void onPause() {
super.onPause();
finish(); // 當新畫面啟動後自動結束 RestartActivity
}
@Override
protected void onDestroy() {
super.onDestroy();
stopOnSwitchFragment();
}
}

View File

@ -0,0 +1,576 @@
package com.unibuy.smartdevice;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Process;
import android.text.InputType;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.unibuy.smartdevice.database.SettingsDao;
import com.unibuy.smartdevice.databinding.ActivityMainBinding;
import com.unibuy.smartdevice.devices.DevNFCPay;
import com.unibuy.smartdevice.devices.DeviceType;
import com.unibuy.smartdevice.devices.Rs232Dev;
import com.unibuy.smartdevice.devices.UsbDev;
import com.unibuy.smartdevice.exception.LogsEmptyException;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsParseException;
import com.unibuy.smartdevice.exception.LogsSettingEmptyException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import com.unibuy.smartdevice.external.HttpAPI;
import com.unibuy.smartdevice.external.HttpTapPay;
import com.unibuy.smartdevice.structure.SettingStructure;
import com.unibuy.smartdevice.tools.ApiPostMainScheduler;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.HandlerMainSchedulerOnClick;
import com.unibuy.smartdevice.tools.ToastHandlerMain;
import com.unibuy.smartdevice.ui.DebugActivity;
import com.unibuy.smartdevice.ui.FontendActivity;
import com.unibuy.smartdevice.ui.ProductListActivity;
import com.unibuy.smartdevice.ui.SettingActivity;
import com.unibuy.smartdevice.ui.SettingTestActivity;
import com.unibuy.smartdevice.ui.SystemSetActivity;
import com.unibuy.smartdevice.ui.XyshjTestActivity;
import com.unibuy.smartdevice.ui.devs.vmc.VmcSlotListActivity;
import com.unibuy.smartdevice.ui.tools.CashMachineSettings;
import com.unibuy.smartdevice.ui.tools.VideoImageMixedPlayer;
import com.unibuy.smartdevice.utils.LanguageHelper;
import java.util.List;
public class MainActivity extends AppCompatActivityAbstract {
@Override
protected Context setCtx() {
return this;
}
@Override
protected Class<?> setCls() {
return this.getClass();
}
@Override
protected HandlerMain setHandlerMain() {
return new ToastHandlerMain(getCtx(), getLogs());
}
private ActivityMainBinding binding;
private HttpAPI httpAPI;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 讀取最後設定語言的設定
// LanguageHelper.applySavedLanguage(this);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
httpAPI = new HttpAPI(getHandlerMain());
//---- 環境尺寸設定 ----
ViewCompat.setOnApplyWindowInsetsListener(binding.main, (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
//---- 環境尺寸設定 ----
initialData();
binding.buttonGotoSetting.setOnClickListener(v -> {
if (!MyApp.getInstance().getMachine().getMachineID().isEmpty()) {
if (MyApp.getInstance().getSuAccess().isEmpty()) {
showLoginDialog(getCtx());
return;
}
}
getTools().gotoActivity(SettingActivity.class);
});
binding.buttonGotoSystemSet.setOnClickListener(v -> {
if (MyApp.getInstance().getMachine().getMachineID().isEmpty()) {
getHandlerMain().start("MainActivity", "@先綁定機器");
return;
}
if (MyApp.getInstance().getSuAccess().isEmpty()) {
showLoginDialog(getCtx());
return;
}
getTools().gotoActivity(SystemSetActivity.class);
});
binding.buttonGotoProductList.setOnClickListener(v -> {
if (MyApp.getInstance().getMachine().getMachineID().isEmpty()) {
getHandlerMain().start("MainActivity", "@先綁定機器");
return;
}
if (MyApp.getInstance().getSuAccess().isEmpty()) {
showLoginDialog(getCtx());
return;
}
getTools().gotoActivity(ProductListActivity.class);
});
binding.buttonGotoSlotList.setOnClickListener(v -> {
if (MyApp.getInstance().getMachine().getMachineID().isEmpty()) {
getHandlerMain().start("MainActivity", "@先綁定機器");
return;
}
if (MyApp.getInstance().getSuAccess().isEmpty()) {
showLoginDialog(getCtx());
return;
}
getTools().gotoActivity(VmcSlotListActivity.class);
});
binding.buttonGotoShoppingPlatform.setOnClickListener(v -> {
if (MyApp.getInstance().getMachine().getMachineID().isEmpty()) {
getHandlerMain().start("MainActivity", "@先綁定機器");
return;
}
boolean hidden = isNavigationReallyHidden();
if (hidden) {
MyApp.getInstance().setSuAccess("");
getTools().gotoActivity(FontendActivity.class);
finish();
} else {
showMustHideSystemBarsDialog();
}
});
binding.buttonGotoSettingTest.setOnClickListener(v -> getTools().gotoActivity(SettingTestActivity.class));
binding.buttonGotoDebug.setOnClickListener(v -> getTools().gotoActivity(DebugActivity.class));
binding.buttonNfcCheckout.setOnClickListener(new ButtonNfcCheckoutOnClick(getHandlerMain()));
binding.buttonNfcReset.setOnClickListener(new ButtonNfcResetOnClick(getHandlerMain()));
binding.buttonQrCodeTest.setOnClickListener(new ButtonQrCodeTestOnClick(getHandlerMain()));
// binding.buttonOtherTest.setOnClickListener(new ButtonOtherTextOnClick(getHandlerMain()));
binding.buttonGotoXyshj.setOnClickListener(new ButtonGotoXyshjOnClick(getHandlerMain()));
binding.buttonClearAds.setOnClickListener(view -> {
VideoImageMixedPlayer.clearAdsCache(this);
});
//鈔票機設定
binding.buttonGotoCash.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 建立 Intent從目前 Activity 跳轉到 CashMachineSettings
Intent intent = new Intent(MainActivity.this, CashMachineSettings.class);
startActivity(intent);
}
});
binding.buttonGotoXyshjTest.setOnClickListener(v -> {
if (MyApp.getInstance().getMachine().getMachineID().isEmpty()) {
getHandlerMain().start("MainActivity", "@先綁定機器");
return;
}
if (MyApp.getInstance().getSuAccess().isEmpty()) {
showLoginDialog(getCtx());
return;
}
getTools().gotoActivity(XyshjTestActivity.class);
});
binding.buttonresetapp.setOnClickListener(v -> {
boolean hidden = isNavigationReallyHidden();
if (hidden) {
ReSetAPP();
} else {
showMustHideSystemBarsDialog();
}
});
}
private static class ButtonQrCodeTestOnClick extends HandlerMainSchedulerOnClick {
public ButtonQrCodeTestOnClick(HandlerMain handlerMain) {
super(handlerMain);
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
boolean openBarcode = true;
try {
UsbDev usbDev = new UsbDev(DeviceType.QRCODE_SCANNER);
handlerMain.start(getClass().getSimpleName(), "@40秒內刷條碼");
byte[] buffer = new byte[1000];
usbDev.read(buffer, 100);
for (int i=0; i<7; i++) {
if (isRun() && openBarcode) {
int size = usbDev.read(buffer, 5000);
if (size > 5) {
String barCodeString = new String(buffer, 0, size);
int sorLength = barCodeString.length();
barCodeString = barCodeString.trim();
int newLength = barCodeString.length();
getLogs().info(barCodeString +" 原碼長:"+sorLength + " 新碼長:" + newLength);
handlerMain.start(getClass().getSimpleName(), getLogs().getMessage());
getLogs().clearMessage();
openBarcode = false;
}
}
}
usbDev.closePort();
} catch (LogsUnsupportedOperationException | LogsIOException | LogsEmptyException e) {
// getLogs().warning(e);
getLogs().warning(e);
}
}
@Override
public void onClick(View v) {
new ButtonQrCodeTestOnClick(getHandlerMain()).start();
}
@Override
public boolean onLongClick(View v) {
return false;
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
public static class ButtonNfcResetOnClick extends HandlerMainSchedulerOnClick {
public ButtonNfcResetOnClick(HandlerMain handlerMain) {
super(handlerMain);
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
try {
Rs232Dev comPort2 = new Rs232Dev(MyApp.getInstance().getComPort2ByNFCPay());
DevNFCPay devNFCPay = new DevNFCPay(handlerMain.getContext());
comPort2.send(devNFCPay.reset());
handlerMain.start(getClass().getSimpleName(), "刷卡機重啟啟動");
} catch (LogsUnsupportedOperationException | LogsIOException e) {
getLogs().warning(e);
}
}
@Override
public void onClick(View v) {
start();
}
@Override
public boolean onLongClick(View v) {
return false;
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
private class ButtonGotoXyshjOnClick extends HandlerMainSchedulerOnClick {
public ButtonGotoXyshjOnClick(HandlerMain srcHandlerMain) {
super(srcHandlerMain);
}
@Override
public void onClick(View view) {
start();
}
@Override
public boolean onLongClick(View view) {
return false;
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
try {
MainActivity.this.getPackageManager().getPackageInfo("com.xyshj.machine", 0);
Intent it = new Intent("android.intent.action.xinyuan.setting");
it.putExtra("showLoginDialog", true);
MainActivity.this.startActivity(it);
android.os.Process.killProcess(Process.myPid());
} catch (PackageManager.NameNotFoundException e) {
handlerMain.start(getSrcHandlerMain().getLogs().getClassName(), "請先安裝興元管理程式");
}
// List<PackageInfo> packages = MainActivity.this.getPackageManager().getInstalledPackages(0);
// for (PackageInfo packageInfo : packages) {
// if ("com.xyshj.machine".equals(packageInfo.packageName)) {
// Intent it = new Intent("android.intent.action.xinyuan.setting");
// it.putExtra("showLoginDialog", true);
// MainActivity.this.startActivity(it);
// android.os.Process.killProcess(Process.myPid());
// return;
// }
// }
// handlerMain.start(getSrcHandlerMain().getLogs().getClassName(), "請先安裝興元管理程式");
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
public static class ButtonNfcCheckoutOnClick extends HandlerMainSchedulerOnClick {
public ButtonNfcCheckoutOnClick(HandlerMain handlerMain) {
super(handlerMain);
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
try {
Rs232Dev comPort2 = new Rs232Dev(MyApp.getInstance().getComPort2ByNFCPay());
DevNFCPay devNFCPay = new DevNFCPay(handlerMain.getContext());
comPort2.send(devNFCPay.checkout());
handlerMain.start(getClass().getSimpleName(), "刷卡機結帳啟動");
} catch (LogsUnsupportedOperationException | LogsIOException e) {
getLogs().warning(e);
}
}
@Override
public void onClick(View v) {
start();
}
@Override
public boolean onLongClick(View v) {
return false;
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
if (event.getAction() == KeyEvent.ACTION_DOWN && event.isLongPress()) {
Toast.makeText(this, "返回主頁", Toast.LENGTH_SHORT).show();
return true;
}
}
return super.dispatchKeyEvent(event);
}
private void initialData() {
if (MyApp.getInstance().getMachine() != null || MyApp.getInstance().getMachine().getMachineID().isEmpty()) {
SettingsDao settingsDao = new SettingsDao(this);
SettingStructure setting = settingsDao.getOne(MyApp.getInstance().getMachine().getClass().getSimpleName());
MyApp.getInstance().getMachine().setMachineID(setting.getData(1));
settingsDao.close();
}
}
public boolean isNavigationReallyHidden() {
WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(binding.main);
if (insets == null) return false;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
// Android 10+ ( 12): 使用 SystemGestures 判斷
// Ges.bottom > 0代表是自動隱藏/全螢幕模式 (可滑出)不允許通過
// Ges.bottom == 0代表是強制隱藏模式 (不可滑出)允許通過
androidx.core.graphics.Insets gestureInsets = insets.getInsets(WindowInsetsCompat.Type.systemGestures());
return gestureInsets.bottom == 0;
} else {
// Android 9 及以下: 維持原有的判斷方式 (檢查導航列高度)
androidx.core.graphics.Insets navInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars());
return navInsets.bottom == 0;
}
}
// 提示對話框 (還原為不帶參數)
private void showMustHideSystemBarsDialog() {
AlertDialog dialog = new AlertDialog.Builder(this)
.setTitle("無法進入購物平台")
.setMessage("進入購物平台前,請先使用 Vol- 按鍵隱藏系統導覽列。")
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 點擊確定後關閉對話框等待使用者按下 V- 按鍵
}
})
.create();
dialog.show();
}
public void showLoginDialog(Context context) {
// 創建一個垂直的 LinearLayout
LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setPadding(50, 20, 50, 10);
// 帳號輸入框
final EditText accessInput = new EditText(context);
accessInput.setHint("帳號");
layout.addView(accessInput);
getTools().setImmHideByFocusChange(accessInput);
getTools().setImmOpenByFocusChange(accessInput);
// 密碼輸入框
final EditText passwordInput = new EditText(context);
passwordInput.setHint("密碼");
passwordInput.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
layout.addView(passwordInput);
getTools().setImmHideByFocusChange(passwordInput);
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle("登入")
.setView(layout)
.setPositiveButton("登入", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String access = accessInput.getText().toString().trim();
String password = passwordInput.getText().toString().trim();
if (access.isEmpty() || password.isEmpty()) {
Toast.makeText(context, "請輸入帳號和密碼", Toast.LENGTH_SHORT).show();
} else {
try {
httpAPI.login(access, password);
} catch (LogsParseException e) {
throw new RuntimeException(e);
} catch (LogsSettingEmptyException e) {
throw new RuntimeException(e);
}
}
getTools().hideSystemBars((Activity) getCtx());
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
getTools().hideSystemBars((Activity) getCtx());
dialog.dismiss();
}
}).create();
// dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
dialog.show();
}
public void ReSetAPP(){
// Intent intent = new Intent(getCtx(), FontendActivity.class); // 改為你的啟動 Activity
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
//
// PendingIntent pendingIntent = PendingIntent.getActivity(
// getCtx(), 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT);
//
// AlarmManager alarmManager = (AlarmManager) getCtx().getSystemService(Context.ALARM_SERVICE);
// alarmManager.setExact(AlarmManager.RTC, System.currentTimeMillis() + 1000, pendingIntent);
//
// // 建議先 log kill
// getLogs().info("🔄 App restarting...");
// android.os.Process.killProcess(android.os.Process.myPid());
Intent intent = new Intent(getApplicationContext(), FontendActivity.class);
// 清空所有 Task重新啟動
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
// 建議搭配 finishAffinity()確保所有舊的 Activity 都被清掉
finishAffinity();
// 建議先 log kill
getLogs().info("🔄MainActivity - App restarting...");
android.os.Process.killProcess(android.os.Process.myPid());
// 完全不需要 killProcess()
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onStart() {
super.onStart();
if (MyApp.getInstance().getMachine().getMachineID().isEmpty()) {
binding.buttonGotoSystemSet.setVisibility(View.GONE);
binding.buttonGotoProductList.setVisibility(View.GONE);
binding.buttonGotoSlotList.setVisibility(View.GONE);
binding.buttonGotoShoppingPlatform.setVisibility(View.GONE);
} else {
binding.buttonGotoSystemSet.setVisibility(View.VISIBLE);
binding.buttonGotoProductList.setVisibility(View.VISIBLE);
binding.buttonGotoSlotList.setVisibility(View.VISIBLE);
binding.buttonGotoShoppingPlatform.setVisibility(View.VISIBLE);
}
}
}

View File

@ -0,0 +1,787 @@
package com.unibuy.smartdevice;
import android.os.Build;
import android.app.Application;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import androidx.work.BackoffPolicy;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.ExistingWorkPolicy;
import androidx.work.OneTimeWorkRequest;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import com.unibuy.smartdevice.controller.DevController;
import com.unibuy.smartdevice.controller.DevXinYuanController;
import com.unibuy.smartdevice.database.MemoDao;
import com.unibuy.smartdevice.database.ProductsDao;
import com.unibuy.smartdevice.database.SettingsDao;
import com.unibuy.smartdevice.database.SlotsDao;
import com.unibuy.smartdevice.devices.ComPort;
import com.unibuy.smartdevice.devices.DevXinYuan;
import com.unibuy.smartdevice.devices.Rs232Dev;
import com.unibuy.smartdevice.devices.SlotField;
import com.unibuy.smartdevice.devices.UsbDev;
import com.unibuy.smartdevice.exception.ErrorCode;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsEmptyException;
import com.unibuy.smartdevice.exception.LogsNoSuchElementException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import com.unibuy.smartdevice.structure.AccessCodeStructure;
import com.unibuy.smartdevice.structure.CashSetStructure;
import com.unibuy.smartdevice.structure.CreditCardReceiptStructure;
import com.unibuy.smartdevice.structure.FreeGiftStructure;
import com.unibuy.smartdevice.structure.MemberVerificationStructure;
import com.unibuy.smartdevice.structure.MemoStructure;
import com.unibuy.smartdevice.structure.ReportAccessCodeStructure;
import com.unibuy.smartdevice.structure.BuyStructure;
import com.unibuy.smartdevice.structure.DevSetStructure;
import com.unibuy.smartdevice.structure.EsunpayStructure;
import com.unibuy.smartdevice.structure.GreenInvoiceStructure;
import com.unibuy.smartdevice.structure.GreenpayMerchantStructure;
import com.unibuy.smartdevice.structure.GreenpaySettingStructure;
import com.unibuy.smartdevice.structure.InvoiceItemStructure;
import com.unibuy.smartdevice.structure.InvoiceStructure;
import com.unibuy.smartdevice.structure.MachineStructure;
import com.unibuy.smartdevice.structure.MarketingPlanStructure;
import com.unibuy.smartdevice.structure.PostInvoiceByGreenStructure;
import com.unibuy.smartdevice.structure.ProductStructure;
import com.unibuy.smartdevice.structure.ReportDispatchInfoStructure;
import com.unibuy.smartdevice.structure.ReportFlowInfoStructure;
import com.unibuy.smartdevice.structure.ReportFreeGiftCodeStructure;
import com.unibuy.smartdevice.structure.ReportInvoiceInfoStructure;
import com.unibuy.smartdevice.structure.ReportSlotListStructure;
import com.unibuy.smartdevice.structure.SettingStructure;
import com.unibuy.smartdevice.structure.SlotStructure;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.ToastHandlerMain;
import com.unibuy.smartdevice.tools.Tools;
import com.unibuy.smartdevice.ui.FontendActivity;
import com.unibuy.smartdevice.ui.tools.VideoEoxPlayer;
import com.unibuy.smartdevice.worker.AppCrashHandler;
import com.unibuy.smartdevice.worker.UploadLogOneTimeWorker;
import com.unibuy.smartdevice.worker.UploadLogPeriodicWorker;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class MyApp extends Application {
private Logs logs;
private static MyApp instance;
public static MyApp getInstance() {
return instance;
}
private int screenWidthPx;
private int screenHeightPx;
private int closeSlot;
private float density;
private ComPort comPort1ByXinYuan;
private ComPort comPort2ByNFCPay;
private List<ProductStructure> uploadProductList;
private List<ProductStructure> productList;
private List<String> fontendAdUrlString;
private Map<Integer, List<SlotStructure>> slotMap;
private List<MarketingPlanStructure> marketingPlanList;
private List<BuyStructure> buyList;
private CashSetStructure cashSetStructure;
private AccessCodeStructure accessCodeStructure;
private FreeGiftStructure freeGiftStructure;
private MemberVerificationStructure memberVerificationStructure;
private ReportAccessCodeStructure reportAccessCodeStructure;
private ReportFreeGiftCodeStructure reportFreeGiftCodeStructure;
private ReportSlotListStructure reportSlotListStructure;
private EsunpayStructure esunpay;
private MachineStructure machine;
private DevSetStructure devSet;
private GreenInvoiceStructure greenInvoice;
private GreenpaySettingStructure greenpaySetting;
private GreenpayMerchantStructure greenpayMerchant;
private static DevXinYuanController devXinYuanController;
public ReportFlowInfoStructure reportFlowInfoData;
public PostInvoiceByGreenStructure postInvoiceByGreenData;
public ReportInvoiceInfoStructure reportInvoiceInfoData;
public InvoiceStructure invoiceData;
public List<InvoiceItemStructure> invoiceItems;
public ReportDispatchInfoStructure reportDispatchInfoData;
public CreditCardReceiptStructure creditCardReceiptInfoData;
public boolean isShowDialog;
public boolean isDetectHost;
public String suAccess;
@Override
public void onCreate() {
super.onCreate();
logs = new Logs(this.getClass());
UsbDev.setUsbManager(getApplicationContext());
Rs232Dev.setSuPath(getApplicationContext());
Tools.setExternalFilesDir(getApplicationContext());
instance = this;
isShowDialog = false;
suAccess = "";
File crashLogFile = new File(getExternalFilesDir(null), "crash_pending.txt");
if (crashLogFile.exists()) {
try {
String content = Tools.readFile(crashLogFile); // 使用上面方法讀檔
logs.info("============================ crash ============================");
logs.update("lastCrashInfo", content);
// 上傳或排程任務
OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(UploadLogOneTimeWorker.class).build();
WorkManager.getInstance(this).enqueueUniqueWork(
"UploadCrashLog",
ExistingWorkPolicy.REPLACE,
request
);
crashLogFile.delete(); // 清除
} catch (IOException e) {
logs.warning(e);
}
}
logs.info("============================ start ============================");
try {
UsbDev.getDeviceInfo(getApplicationContext());
} catch (LogsUnsupportedOperationException e) {
logs.warning(e);
}
this.comPort1ByXinYuan = ComPort.COM_PORT_1;
this.comPort2ByNFCPay = ComPort.COM_PORT_2;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
this.comPort1ByXinYuan = ComPort.COM_PORT_S1;
this.comPort2ByNFCPay = ComPort.COM_PORT_S2;
}
this.devSet = new DevSetStructure(true, false, false, true, true,
true, true, false, false,true,true,true,true,true);
this.machine = new MachineStructure("");
this.esunpay = new EsunpayStructure("", "", "");
this.greenInvoice = new GreenInvoiceStructure("", "", "", "");
this.greenpaySetting = new GreenpaySettingStructure(
"",
"",
"",
"",
"",
"",
"",
"");
this.greenpayMerchant = new GreenpayMerchantStructure(
"",
"",
"",
"",
"",
"",
"",
"",
"",
"");
this.cashSetStructure = new CashSetStructure(true, true, true, true, true, true, true);
this.accessCodeStructure = new AccessCodeStructure("");
this.freeGiftStructure = new FreeGiftStructure("");
this.memberVerificationStructure = new MemberVerificationStructure("", 0, "", 0);
this.reportAccessCodeStructure = new ReportAccessCodeStructure("", 0, 0, "", "");
this.reportFreeGiftCodeStructure = new ReportFreeGiftCodeStructure("", 0, "", 0, 0, "");
this.reportSlotListStructure = new ReportSlotListStructure("","","","");
this.fontendAdUrlString = new ArrayList<>();
ToastHandlerMain toastHandlerMain = new ToastHandlerMain(getApplicationContext(), logs);
if (this.devXinYuanController != null) {
this.devXinYuanController.shutdown();
}
this.devXinYuanController = new DevXinYuanController(toastHandlerMain);
devXinYuanController.start();
devXinYuanController.addSendBuffer(devXinYuanController.getDevXinYuan().syncPackNo((byte)0x01));
devXinYuanController.getReadBufferByNow(new DevController.ReadBufferOnScheduler(toastHandlerMain) {
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected Class<?> setCls() {
return getClass();
}
@Override
public void readBufferOnScheduler(DevController devController, HandlerMain handlerMain) {
int moneySwitchOkCount = 0;
for(byte[] buffer: devController.getReadBufferByMax()) {
DevXinYuan.VMC vmc = DevXinYuanController.vmcMap.get(buffer[0]);
switch (vmc) {
case VMC_29_MONEY_SWITCH:
if (buffer[1] == 0x00) {
moneySwitchOkCount++;
}
break;
}
}
}
});
devXinYuanController.addSendBuffer(devXinYuanController.getDevXinYuan().inComeByIPC((byte) 0x08, 9999));
devXinYuanController.addSendBuffer(devXinYuanController.getDevXinYuan().setMoneyType((byte) 0x01, (byte) 0x00, (byte) 0x00));
devXinYuanController.addSendBuffer(devXinYuanController.getDevXinYuan().setMoneyType((byte) 0x02, (byte) 0x00, (byte) 0x00));
initialSettingData();
initialSystemSet(getApplicationContext());
initialReportData();
calculateScreenSize();
this.uploadProductList = new ArrayList<>();
this.productList = new ArrayList<>();
initialProductData();
this.slotMap = new HashMap<>();
initialSlotData();
this.marketingPlanList = new ArrayList<>();
this.buyList = new ArrayList<>();
PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(
UploadLogPeriodicWorker.class,
UploadLogPeriodicWorker.getTimeinByMinute(),
TimeUnit.MINUTES)
.setBackoffCriteria(
BackoffPolicy.EXPONENTIAL,
2,
TimeUnit.MINUTES)
.build();
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
"PeriodicWorkRequest", // 確保這個名稱的 WorkRequest 只存在一個
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
periodicWorkRequest
);
Thread.setDefaultUncaughtExceptionHandler(new AppCrashHandler(this));
}
public void initialReportData() {
setReportFlowInfoData(new ReportFlowInfoStructure("",0, "", "", "", 0, "", "", 0, 0, 0, new JSONArray()));
setPostInvoiceByGreenData(new PostInvoiceByGreenStructure("","", 0, new InvoiceStructure("", "", "", ""), new ArrayList<>()));
setReportInvoiceInfoData(new ReportInvoiceInfoStructure("", "", "", "", "", "", ""));
setInvoiceData(new InvoiceStructure("", "", "", ""));
setInvoiceItems(new ArrayList<>());
setReportDispatchInfoData(new ReportDispatchInfoStructure("", 0, "", 0, 0, "", 0, "", "", 0, 0, 0));
setReportAccessCodeStructure(new ReportAccessCodeStructure("", 0, 0, "", ""));
setAccessCodeStructure(new AccessCodeStructure(""));
setFreeGiftStructure(new FreeGiftStructure(""));
// setReportFreeGiftCodeStructure(new ReportFreeGiftCodeStructure("", 0, "", 0, 0, ""));
setMemberVerificationStructure(new MemberVerificationStructure("", 0, "", 0));
//addReportDispatchInfoData(new ReportDispatchInfoStructure("", 0, "", 0, 0, "", 0, "", "", 0, 0, 0));
}
private void initialSystemSet(Context context) {
MemoDao memoDao = new MemoDao(context);
if (memoDao.existOnlyOne(MyApp.getInstance().getDevSet().getClass().getSimpleName())) {
JSONObject jsonObject = memoDao.getOnlyOne(MyApp.getInstance().getDevSet().getClass().getSimpleName()).getData();
logs.debug("initialSystemSet:" + jsonObject.toString());
try {
MyApp.getInstance().getDevSet().setVMC(jsonObject.getBoolean("VMC"));
MyApp.getInstance().getDevSet().setElectic(jsonObject.getBoolean("Electic"));
MyApp.getInstance().getDevSet().setShoppingCar(jsonObject.getBoolean("ShoppingCar"));
MyApp.getInstance().getDevSet().setInvoice(jsonObject.getBoolean("Invoice"));
MyApp.getInstance().getDevSet().setDevNFCPay(jsonObject.getBoolean("DevNFCPay"));
MyApp.getInstance().getDevSet().setDevEsunPay(jsonObject.getBoolean("DevEsunPay"));
MyApp.getInstance().getDevSet().setDevTapPay(jsonObject.getBoolean("DevTapPay"));
MyApp.getInstance().getDevSet().setDevCash(jsonObject.getBoolean("DevCash"));
MyApp.getInstance().getDevSet().setDevLinePay(jsonObject.getBoolean("DevLinePay"));
} catch (JSONException e) {
new Logs(MyApp.class).warning(e);
}
}
if (memoDao.existOnlyOne(MyApp.getInstance().getCashSetStructure().getClass().getSimpleName())) {
JSONObject jsonObject = memoDao.getOnlyOne(MyApp.getInstance().getCashSetStructure().getClass().getSimpleName()).getData();
logs.debug("initialSystemSet:" + jsonObject.toString());
try {
MyApp.getInstance().getCashSetStructure().setBillF1000(jsonObject.getBoolean("BillF1000"));
MyApp.getInstance().getCashSetStructure().setBillE500(jsonObject.getBoolean("BillE500"));
MyApp.getInstance().getCashSetStructure().setBillD100(jsonObject.getBoolean("BillD100"));
MyApp.getInstance().getCashSetStructure().setCoinF50(jsonObject.getBoolean("CoinF50"));
MyApp.getInstance().getCashSetStructure().setCoinE10(jsonObject.getBoolean("CoinE10"));
MyApp.getInstance().getCashSetStructure().setCoinD5(jsonObject.getBoolean("CoinD5"));
MyApp.getInstance().getCashSetStructure().setCoinC1(jsonObject.getBoolean("CoinC1"));
} catch (JSONException e) {
new Logs(MyApp.class).warning(e);
}
}
}
public static void saveSystemSet(Context context) {
MemoDao memoDao = new MemoDao(context);
try {
JSONObject systemSetByJsonObject = new JSONObject();
systemSetByJsonObject.put("VMC", MyApp.getInstance().getDevSet().isVMC());
systemSetByJsonObject.put("Electic", MyApp.getInstance().getDevSet().isElectic());
systemSetByJsonObject.put("ShoppingCar", MyApp.getInstance().getDevSet().isShoppingCar());
systemSetByJsonObject.put("Invoice", MyApp.getInstance().getDevSet().isInvoice());
systemSetByJsonObject.put("DevNFCPay", MyApp.getInstance().getDevSet().isDevNFCPay());
systemSetByJsonObject.put("DevEsunPay", MyApp.getInstance().getDevSet().isDevEsunPay());
systemSetByJsonObject.put("DevTapPay", MyApp.getInstance().getDevSet().isDevTapPay());
systemSetByJsonObject.put("DevCash", MyApp.getInstance().getDevSet().isDevCash());
systemSetByJsonObject.put("DevLinePay", MyApp.getInstance().getDevSet().isDevLinePay());
JSONObject cashSetByJsonObject = new JSONObject();
cashSetByJsonObject.put("BillF1000", MyApp.getInstance().getCashSetStructure().isBillF1000());
cashSetByJsonObject.put("BillE500", MyApp.getInstance().getCashSetStructure().isBillE500());
cashSetByJsonObject.put("BillD100", MyApp.getInstance().getCashSetStructure().isBillD100());
cashSetByJsonObject.put("CoinF50", MyApp.getInstance().getCashSetStructure().isCoinF50());
cashSetByJsonObject.put("CoinE10", MyApp.getInstance().getCashSetStructure().isCoinE10());
cashSetByJsonObject.put("CoinD5", MyApp.getInstance().getCashSetStructure().isCoinD5());
cashSetByJsonObject.put("CoinC1", MyApp.getInstance().getCashSetStructure().isCoinC1());
memoDao.insertOnlyOne(new MemoStructure(
MyApp.getInstance().getDevSet().getClass().getSimpleName(),
systemSetByJsonObject
, new JSONObject()));
memoDao.mapUpdate();
new Logs(MyApp.class).info("saveSystemSet count:" + memoDao.getCount(MyApp.getInstance().getDevSet().getClass().getSimpleName()));
memoDao.insertOnlyOne(new MemoStructure(
MyApp.getInstance().getCashSetStructure().getClass().getSimpleName(),
cashSetByJsonObject
, new JSONObject()));
memoDao.mapUpdate();
new Logs(MyApp.class).info("saveSystemSet count:" + memoDao.getCount(MyApp.getInstance().getCashSetStructure().getClass().getSimpleName()));
} catch (JSONException e) {
new Logs(MyApp.class).warning(e);
}
}
public static void updateLog(Context context) {
OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(UploadLogOneTimeWorker.class)
.setInitialDelay(5, TimeUnit.SECONDS)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 5, TimeUnit.MINUTES)
.build();
WorkManager.getInstance(context).enqueueUniqueWork(
"oneTimeWorkRequest", // 設定唯一名稱避免重複
ExistingWorkPolicy.REPLACE,
oneTimeWorkRequest
);
}
public void initialSettingData() {
SettingsDao settingsDao = new SettingsDao(getApplicationContext());
if (MyApp.getInstance().getMachine().getMachineID().isEmpty()) {
SettingStructure setting = settingsDao.getOne(MyApp.getInstance().getMachine().getClass().getSimpleName());
logs.info("initialSettingData:" + setting.toString());
MyApp.getInstance().getMachine().setMachineID(setting.getData(1));
}
if (MyApp.getInstance().getGreenInvoice().getGreenMerchantID().isEmpty()) {
SettingStructure setting = settingsDao.getOne(MyApp.getInstance().getGreenInvoice().getClass().getSimpleName());
MyApp.getInstance().getGreenInvoice().setGreenMerchantID(setting.getData(0));
MyApp.getInstance().getGreenInvoice().setGreenHashKey(setting.getData(1));
MyApp.getInstance().getGreenInvoice().setGreenHashIV(setting.getData(2));
MyApp.getInstance().getGreenInvoice().setGreenEmail(setting.getData(3));
}
if (MyApp.getInstance().getEsunpay().getStoreID().isEmpty()) {
SettingStructure setting = settingsDao.getOne(MyApp.getInstance().getEsunpay().getClass().getSimpleName());
MyApp.getInstance().getEsunpay().setStoreID(setting.getData(0));
MyApp.getInstance().getEsunpay().setTermID(setting.getData(1));
MyApp.getInstance().getEsunpay().setHash(setting.getData(2));
}
if (MyApp.getInstance().getGreenpaySetting().getAppId().isEmpty()) {
SettingStructure setting = settingsDao.getOne(MyApp.getInstance().getGreenpaySetting().getClass().getSimpleName());
MyApp.getInstance().getGreenpaySetting().setAppId(setting.getData(0));
MyApp.getInstance().getGreenpaySetting().setAppKey(setting.getData(1));
MyApp.getInstance().getGreenpaySetting().setPartnerKey(setting.getData(2));
MyApp.getInstance().getGreenpaySetting().setCtbcMerchantId(setting.getData(3));
MyApp.getInstance().getGreenpaySetting().setNcccMerchantId(setting.getData(4));
MyApp.getInstance().getGreenpaySetting().setTaishinMerchantId(setting.getData(5));
MyApp.getInstance().getGreenpaySetting().setEsunMerchantId(setting.getData(6));
MyApp.getInstance().getGreenpaySetting().setGpuseMerchantId(setting.getData(7));
SettingStructure setting2 = settingsDao.getOne(MyApp.getInstance().getGreenpayMerchant().getClass().getSimpleName());
MyApp.getInstance().getGreenpayMerchant().setLineMerchantId(setting2.getData(0));
MyApp.getInstance().getGreenpayMerchant().setPsMerchantId(setting2.getData(1));
MyApp.getInstance().getGreenpayMerchant().setEasyMerchantId(setting2.getData(2));
MyApp.getInstance().getGreenpayMerchant().setPiMerchantId(setting2.getData(3));
MyApp.getInstance().getGreenpayMerchant().setJkoMerchantId(setting2.getData(4));
MyApp.getInstance().getGreenpayMerchant().setDirectMerchantId(setting2.getData(5));
MyApp.getInstance().getGreenpayMerchant().setAppleMerchantId(setting2.getData(6));
MyApp.getInstance().getGreenpayMerchant().setGoogleMerchantId(setting2.getData(7));
MyApp.getInstance().getGreenpayMerchant().setSamsungMerchantId(setting2.getData(8));
MyApp.getInstance().getGreenpayMerchant().setAtomeMerchantId(setting2.getData(9));
}
if (MyApp.getInstance().getFontendAdUrlString().isEmpty()) {
List<SettingStructure> settingList = settingsDao.getWhere(VideoEoxPlayer.class.getSimpleName());
for (SettingStructure setting: settingList) {
MyApp.getInstance().getFontendAdUrlString().add(setting.getData(0));
}
}
settingsDao.close();
}
private void initialProductData() {
if (MyApp.getInstance().getProductList().isEmpty()) {
ProductsDao productsDao = new ProductsDao(this);
for (ProductStructure product: productsDao.getAll()) {
MyApp.getInstance().getProductList().add(product);
}
productsDao.close();
logs.info("product count:"+ MyApp.getInstance().getProductList().size());
}
}
public void initialSlotData() {
logs.debug("initialSlotData");
//開架構
for (SlotField slotField: SlotField.values()) {
if (!getInstance().getSlotMap().containsKey(slotField.getField())) {
getInstance().getSlotMap().put(slotField.getField(), new ArrayList<>());
logs.info(slotField.getField()+" slot db open");
}
}
//查詢資料庫
SlotsDao slotsDao = new SlotsDao(this);
Map<Integer, List<SlotStructure>> slotMapNew = slotsDao.getAll();
for (SlotField slotField: SlotField.values()) {
if (getInstance().getSlotList(slotField.getField()).isEmpty() && slotMapNew.get(slotField.getField()) != null && !slotMapNew.get(slotField.getField()).isEmpty()) {
List<SlotStructure> slotList = slotMapNew.get(slotField.getField());
for (SlotStructure slot : slotList) {
getInstance().getSlotList(slotField.getField()).add(slot);
}
logs.info(slotField.getField()+" slot db count:"+getInstance().getSlotList(slotField.getField()).size());
}
}
slotsDao.close();
//無資料就初始化
if (getInstance().getSlotList(SlotField.VMC.getField()).isEmpty()) {
for (int i = 1; i <= 60; i++) {
getInstance().getSlotList(SlotField.VMC.getField()).add(new SlotStructure(SlotField.VMC.getField(), i,
new ProductStructure("?", "", "", 0, 0, 0, 0, "", "","",""),
0));
}
logs.info(SlotField.VMC.getField()+" slot init count:" + getInstance().getSlotList(SlotField.VMC.getField()).size());
}
if (getInstance().getSlotList(SlotField.ELECTRIC.getField()).isEmpty()) {
for (int i = 1; i <= 10; i++) {
getInstance().getSlotList(SlotField.ELECTRIC.getField()).add(new SlotStructure(SlotField.ELECTRIC.getField(), i,
new ProductStructure("?", "", "", 0, 0, 0, 0, "", "","",""),
0));
}
logs.info(SlotField.ELECTRIC.getField()+" slot init count:" + getInstance().getSlotList(SlotField.ELECTRIC.getField()).size());
}
}
private void calculateScreenSize() {
// 取得 WindowManager
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
// 取得螢幕尺寸
if (wm != null) {
wm.getDefaultDisplay().getMetrics(metrics);
this.screenWidthPx = metrics.widthPixels;
this.screenHeightPx = metrics.heightPixels;
density = metrics.density; // 保存密度值
}
}
// 新增 px dp 的函數
public int pxToDp(int px) {
return Math.round(px / density);
}
// 新增 dp px 的函數可選
public int dpToPx(int dp) {
return Math.round(dp * density);
}
public int getScreenWidthPx() {
return screenWidthPx;
}
public int getScreenHeightPx() {
return screenHeightPx;
}
public ComPort getComPort1ByXinYuan() {
return comPort1ByXinYuan;
}
public ComPort getComPort2ByNFCPay() {
return comPort2ByNFCPay;
}
public List<ProductStructure> getUploadProductList() {
return uploadProductList;
}
public List<ProductStructure> getProductList() {
return productList;
}
public List<String> getFontendAdUrlString() {
return fontendAdUrlString;
}
public ProductStructure getProduct(String productId) throws LogsNoSuchElementException {
for (ProductStructure product: getProductList()) {
if (product.getProductID().equals(productId)) {
return product;
}
}
throw new LogsNoSuchElementException(logs, "get product "+productId+" not found");
}
public Map<Integer, List<SlotStructure>> getSlotMap() {
return slotMap;
}
public List<SlotStructure> getSlotList(int field) {
return getSlotMap().get(field);
}
public SlotStructure getSlotData(int field, int slot) throws LogsEmptyException {
for (SlotStructure slotData: getSlotList(field)) {
if (slotData.getSlot() == slot) {
return slotData;
}
}
throw new LogsEmptyException(logs, "Slot data not found");
}
public SlotStructure getSlotDataByPid(int field, String pid) throws LogsEmptyException {
int i = 0;
for (SlotStructure slotData: getSlotList(field)) {
i += 1;
logs.info("AAAAAAAAAAAAAAAAAAAAAAAAAAAA0"+i);
if (slotData.getProduct().getProductID().equals(String.valueOf(pid))) {
if(slotData.getCount() > 0) {
return slotData;
}
}
}
throw new LogsEmptyException(logs, "Slot data not found");
}
public SlotStructure getSlotDataByPid(String pid) throws LogsEmptyException {
for (SlotField slotField: SlotField.values()) {
try {
return getSlotDataByPid(slotField.getField(), pid);
} catch (LogsEmptyException e) {
}
}
throw new LogsEmptyException(logs, "Slot data not found");
}
public List<MarketingPlanStructure> getMarketingPlanList() {
return marketingPlanList;
}
public List<BuyStructure> getBuyList() {
return buyList;
}
public EsunpayStructure getEsunpay() {
return esunpay;
}
public MachineStructure getMachine() {
return machine;
}
public GreenInvoiceStructure getGreenInvoice() {
return greenInvoice;
}
public GreenpaySettingStructure getGreenpaySetting() {
return greenpaySetting;
}
public GreenpayMerchantStructure getGreenpayMerchant() {
return greenpayMerchant;
}
public DevXinYuanController getDevXinYuanController() {
return devXinYuanController;
}
public void setReportFlowInfoData(ReportFlowInfoStructure reportFlowInfoData) {
this.reportFlowInfoData = reportFlowInfoData;
}
public ReportFlowInfoStructure getReportFlowInfoData() {
return reportFlowInfoData;
}
public void setPostInvoiceByGreenData(PostInvoiceByGreenStructure postInvoiceByGreenData) {
this.postInvoiceByGreenData = postInvoiceByGreenData;
}
public PostInvoiceByGreenStructure getPostInvoiceByGreenData() {
return postInvoiceByGreenData;
}
public void setReportInvoiceInfoData(ReportInvoiceInfoStructure reportInvoiceInfoData) {
this.reportInvoiceInfoData = reportInvoiceInfoData;
}
public void setReportAccessCodeStructure(ReportAccessCodeStructure reportAccessCodeStructure) {
this.reportAccessCodeStructure = reportAccessCodeStructure;
}
public void setReportFreeGiftCodeStructure(ReportFreeGiftCodeStructure reportFreeGiftCodeStructure) {
this.reportFreeGiftCodeStructure = reportFreeGiftCodeStructure;
}
public ReportFreeGiftCodeStructure getReportFreeGiftCodeStructure() {
return reportFreeGiftCodeStructure;
}
public ReportInvoiceInfoStructure getReportInvoiceInfoData() {
return reportInvoiceInfoData;
}
public void setInvoiceData(InvoiceStructure invoiceData) {
this.invoiceData = invoiceData;
}
public InvoiceStructure getInvoiceData() {
return invoiceData;
}
public List<InvoiceItemStructure> getInvoiceItems() {
return invoiceItems;
}
public void setInvoiceItems(List<InvoiceItemStructure> invoiceItems) {
this.invoiceItems = invoiceItems;
}
public void setReportDispatchInfoData(ReportDispatchInfoStructure reportDispatchInfoData) {
this.reportDispatchInfoData = reportDispatchInfoData;
}
public ReportDispatchInfoStructure getReportDispatchInfoData() {
return reportDispatchInfoData;
}
public void setCreditCardReceiptInfoData(CreditCardReceiptStructure creditCardReceiptInfoData){
this.creditCardReceiptInfoData = creditCardReceiptInfoData;
}
public CreditCardReceiptStructure getCreditCardReceiptInfoData() {
return creditCardReceiptInfoData;
}
public DevSetStructure getDevSet() {
return devSet;
}
public ReportAccessCodeStructure getReportAccessCodeStructure() {
return reportAccessCodeStructure;
}
public ReportSlotListStructure getReportSlotListStructure(){
return reportSlotListStructure;
}
public CashSetStructure getCashSetStructure() {
return cashSetStructure;
}
public AccessCodeStructure getAccessCodeStructure() {
return accessCodeStructure;
}
public void setAccessCodeStructure(AccessCodeStructure accessCodeStructure) {
this.accessCodeStructure = accessCodeStructure;
}
public FreeGiftStructure getFreeGiftStructure() {
return freeGiftStructure;
}
public void setFreeGiftStructure(FreeGiftStructure freeGiftStructure) {
this.freeGiftStructure = freeGiftStructure;
}
public MemberVerificationStructure getMemberVerificationStructure() {
return memberVerificationStructure;
}
public void setMemberVerificationStructure(MemberVerificationStructure memberVerificationStructure) {
this.memberVerificationStructure = memberVerificationStructure;
}
public int getCloseSlot() {
return closeSlot;
}
public void setCloseSlot(int closeSlot) {
this.closeSlot = closeSlot;
}
public boolean isShowDialog() {
return isShowDialog;
}
public void setShowDialog(boolean showDialog) {
isShowDialog = showDialog;
}
public String getSuAccess() {
return suAccess;
}
public void setSuAccess(String suAccess) {
this.suAccess = suAccess;
}
public boolean isDetectHost() {
return isDetectHost;
}
public void setDetectHost(boolean detectHost) {
isDetectHost = detectHost;
}
}

View File

@ -0,0 +1,186 @@
package com.unibuy.smartdevice;
import com.unibuy.smartdevice.exception.ErrorCode;
import com.unibuy.smartdevice.exception.Logs;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class SchedulerAbstract implements Runnable {
public class SchedulerThreadFactory implements ThreadFactory {
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
public SchedulerThreadFactory(String className) {
namePrefix = className + "-Thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, namePrefix + threadNumber.getAndIncrement());
thread.setDaemon(true); // 設定為守護執行緒
return thread;
}
}
private volatile ScheduledExecutorService scheduler;
private final Logs logs;
private volatile boolean isRun;
private boolean isLoop;
private String description;
public boolean isRun() {
return isRun;
}
public void setRun(boolean run) {
this.isRun = run;
}
public Logs getLogs() {
return logs;
}
public boolean isLoop() {
return isLoop;
}
private void setLoop(boolean loop) {
isLoop = loop;
}
public String getDescription() {
return description;
}
public ScheduledExecutorService getScheduler() {
return scheduler;
}
public SchedulerAbstract() {
this.logs = new Logs(setCls());
this.isRun = true;
this.description = description();
}
@Override
public void run() {
try {
if (isRun()) {
execute(); // 執行具體邏輯
if (isLoop()) {
logs.info("loop run: " + getDescription());
} else {
logs.info("one run: " + getDescription());
shutdown();
}
} else {
shutdown();
}
} catch (Exception e) {
logs.warning(e);
}
}
private synchronized void initScheduler() {
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(1, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
scheduler = null;
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
scheduler = null;
}
}
// int maxThreads = Runtime.getRuntime().availableProcessors() * 2;
// scheduler = Executors.newScheduledThreadPool(maxThreads, new SchedulerThreadFactory(description()));
scheduler = Executors.newSingleThreadScheduledExecutor(new SchedulerThreadFactory(description()));
}
private void perform(long delay, TimeUnit timeUnit) {
initScheduler();
setLoop(false);
setRun(true);
scheduler.schedule(this, delay, timeUnit);
}
private void perform(long delay, long period, TimeUnit timeUnit) {
initScheduler();
setLoop(true);
setRun(true);
scheduler.scheduleWithFixedDelay(this, delay, period, timeUnit);
}
private void perform() {
initScheduler();
setLoop(false);
setRun(true);
scheduler.execute(this);
}
public void start() {
if (isShutdown()) {
perform();
} else {
logs.debug("Scheduler is already running, cannot start again." + description());
}
}
public void start(long delay, TimeUnit timeUnit) {
if (isShutdown()) {
perform(delay, timeUnit);
} else {
logs.debug("Scheduler is already running, cannot start again." + description());
}
}
public void start(long delay, long period, TimeUnit timeUnit) {
if (isShutdown()) {
perform(delay, period, timeUnit);
} else {
logs.debug("Scheduler is already running, cannot start again." + description());
}
}
// 判斷排程器是否已關閉
public boolean isShutdown() {
return scheduler == null || scheduler.isShutdown();
}
public void shutdown() {
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(1, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
scheduler = null;
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
scheduler = null;
}
}
}
// 重啟排程器
public void resetScheduler() {
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdownNow(); // 停止並重啟排程器
}
initScheduler();
}
protected abstract Class<?> setCls();
protected abstract String description();
protected abstract void execute();
// protected abstract void exception(ErrorCode errorCode, String message);
}

View File

@ -0,0 +1,67 @@
package com.unibuy.smartdevice.controller;
import com.unibuy.smartdevice.devices.DeviceType;
import com.unibuy.smartdevice.devices.PortTools;
import com.unibuy.smartdevice.devices.UsbDev;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsEmptyException;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import com.unibuy.smartdevice.tools.HandlerMain;
public class DevBarCodeController extends DevController {
private Logs logs;
private UsbDev usbDev;
public DevBarCodeController(HandlerMain handlerMain) {
super(20, handlerMain);
this.logs = new Logs(getClass());
try {
this.usbDev = new UsbDev(DeviceType.QRCODE_SCANNER);
} catch (LogsEmptyException | LogsUnsupportedOperationException | LogsIOException e) {
// getLogs().warning(e);
getLogs().warning(e);
}
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void close(HandlerMain handlerMain) {
try {
usbDev.closePort();
} catch (LogsIOException e) {
// getLogs().warning(e);
getLogs().warning(e);
}
}
@Override
protected void execute(HandlerMain handlerMain) {
try {
while (isRun() && isReadBufferMax()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
byte[] buffer = new byte[20];
int size = usbDev.read(buffer, 1000);
if (size > 0) {
setRun(false);
byte[] code = PortTools.catByteArrays(buffer, 0, size);
publishReadBuffer(code);
}
}
} catch (LogsUnsupportedOperationException | LogsIOException e) {
getLogs().warning(e);
}
}
@Override
protected Class<?> setCls() {
return getClass();
}
}

View File

@ -0,0 +1,171 @@
package com.unibuy.smartdevice.controller;
import com.unibuy.smartdevice.SchedulerAbstract;
import com.unibuy.smartdevice.devices.PortTools;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.HandlerMainScheduler;
import com.unibuy.smartdevice.tools.OwnScheduler;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public abstract class DevController extends HandlerMainScheduler {
private Logs logs;
private List<byte[]> sendBuffers;
private int readBufferMax;
private int delayMillisByReadBuffer;
public void addSendBuffer(byte[] buffer) {
if (this.isRun()) {
logs.info("sendBuffers max:" + sendBuffers.size());
if (sendBuffers.size() > 50) {
setRun(false);
return;
}
sendBuffers.add(buffer);
}
}
public void getReadBuffer(ReadBufferOnScheduler readBufferOnScheduler, long delayMillis) {
if (this.isRun()) {
readBufferOnScheduler.setDevController(this);
readBufferOnScheduler.start(delayMillis, TimeUnit.MILLISECONDS);
}
}
public void getReadBufferByNow(ReadBufferOnScheduler readBufferOnScheduler) {
getReadBufferByNow(readBufferOnScheduler, getDelayMillisByReadBuffer());
}
public void getReadBufferByNow(ReadBufferOnScheduler readBufferOnScheduler, long delayMillis) {
clearReadBuffers();
getLogs().debug("readBuffer size:" + getCountByReadBuffer());
getReadBuffer(readBufferOnScheduler, delayMillis);
}
public byte[] getSendBuffer(int index) {
return sendBuffers.get(index);
}
public byte[] getSendBufferByFirst() {
return getSendBuffer(0);
}
public void removeSendBufferByFirst() {
if (!sendBuffers.isEmpty()) {
sendBuffers.remove(0);
}
}
public int getCountBySendBuffer() {
if (sendBuffers == null) return 0;
return sendBuffers.size();
}
public void clearSendBuffers() {
sendBuffers.clear();
}
public abstract static class ReadBufferOnScheduler extends HandlerMainScheduler {
private DevController devController;
public ReadBufferOnScheduler(HandlerMain handlerMain) {
super(handlerMain);
}
public void setDevController(DevController devController) {
this.devController = devController;
}
@Override
protected String description() {
if (this.devController != null) {
return this.devController.setCls().getSimpleName();
} else {
return getClass().getSimpleName();
}
}
public abstract void readBufferOnScheduler(DevController devController, HandlerMain handlerMain);
@Override
protected void execute(HandlerMain handlerMain) {
readBufferOnScheduler(this.devController, handlerMain);
}
}
private List<byte[]> readBuffers;
public void publishReadBuffer(byte[] buffer1, byte[] buffer2) {
byte[] buffer = PortTools.concatByteArrays(buffer1, buffer2);
publishReadBuffer(buffer);
}
public void publishReadBuffer(byte[] buffer) {
if (!isReadBufferMax()) {
readBuffers.add(buffer);
}
}
public boolean isReadBufferMax() {
return getCountByReadBuffer() >= readBufferMax;
}
public List<byte[]> getReadBuffer(int count) {
List<byte[]> buffers = new ArrayList<>();
for (int index=0; index<count; index++) {
byte[] buffer = getReadBuffer();
if (buffer.length > 0) buffers.add(buffer);
else break;
}
return buffers;
}
public List<byte[]> getReadBufferByMax() {
int size = readBuffers.size();
return readBuffers;
}
public byte[] getReadBuffer() {
byte[] readBuffer = getCountByReadBuffer() > 0 ? readBuffers.get(0): new byte[0];
if (getCountByReadBuffer() > 0) readBuffers.remove(0);
return readBuffer;
}
public void limitReadBuffer(int max) {
if (getCountByReadBuffer()>max) getReadBuffer();
}
public int getCountByReadBuffer() {
if (readBuffers == null) return 0;
return readBuffers.size();
}
public void clearReadBuffers() {
readBuffers.clear();
}
public DevController(int readBufferMax, HandlerMain handlerMain) {
super(handlerMain);
this.logs = new Logs(getClass());
this.sendBuffers = new CopyOnWriteArrayList<>();
this.readBuffers = new CopyOnWriteArrayList<>();
this.readBufferMax = readBufferMax;
this.delayMillisByReadBuffer = 2000;
}
public int getDelayMillisByReadBuffer() {
return delayMillisByReadBuffer;
}
public void setDelayMillisByReadBuffer(int delayMillisByReadBuffer) {
this.delayMillisByReadBuffer = delayMillisByReadBuffer;
}
}

View File

@ -0,0 +1,88 @@
package com.unibuy.smartdevice.controller;
import com.unibuy.smartdevice.devices.ComPort;
import com.unibuy.smartdevice.devices.DevDigitalDisplay;
import com.unibuy.smartdevice.devices.Rs232Dev;
import com.unibuy.smartdevice.exception.ErrorCode;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import com.unibuy.smartdevice.tools.HandlerMain;
public class DevDigitalDisplayController extends DevController {
private Rs232Dev comPort;
public DevDigitalDisplayController(HandlerMain handlerMain) {
super(10, handlerMain);
try {
this.comPort = new Rs232Dev(ComPort.COM_PORT_6);
} catch (LogsUnsupportedOperationException | LogsIOException e) {
// getLogs().warning(e);
getLogs().warning(e);
}
}
public void devPut(int slot, int h, int m, int min) throws LogsIOException {
byte[] buffer = DevDigitalDisplay.getBuffer(slot, h, m, min);
addSendBuffer(buffer);
}
@Override
protected void close(HandlerMain handlerMain) {
try {
if (this.comPort != null) {
this.comPort.closePort();
}
} catch (LogsIOException e) {
getLogs().warning(e);
}
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
try {
while (isRun() && getCountBySendBuffer() == 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if (isRun() && getCountBySendBuffer() > 0) {
while (isRun() && getCountBySendBuffer() > 0) {
this.comPort.send(getSendBufferByFirst());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
removeSendBufferByFirst();
byte[] readBuffer = this.comPort.readListen(100, 5);
if (readBuffer.length > 0) {
publishReadBuffer(readBuffer);
}
}
}
} catch (LogsIOException e) {
// getLogs().warning(e);
getLogs().warning(e);
}
}
// @Override
// protected void exception(ErrorCode errorCode, String message, HandlerMain handlerMain) {
// handlerMain.error(getClass().getSimpleName(), errorCode, message);
// setRun(false);
// }
@Override
protected Class<?> setCls() {
return getClass();
}
}

View File

@ -0,0 +1,91 @@
package com.unibuy.smartdevice.controller;
import com.unibuy.smartdevice.devices.ComPort;
import com.unibuy.smartdevice.devices.PortTools;
import com.unibuy.smartdevice.devices.Rs232Dev;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsSecurityException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import com.unibuy.smartdevice.tools.HandlerMain;
public class DevElectricController extends DevController {
private Rs232Dev comPort;
public DevElectricController(HandlerMain handlerMain) throws LogsSecurityException, LogsUnsupportedOperationException, LogsIOException {
super( 10, handlerMain);
this.comPort = new Rs232Dev(ComPort.COM_PORT_3);
}
public void devSwitch(int slot, int h, int m, int min) throws LogsIOException {
byte[] sendBuffer = new byte[] {0x02, 0x01, 0x01};
sendBuffer = PortTools.concatByteArrays(sendBuffer, PortTools.intToByte8(slot, 1));
sendBuffer = PortTools.concatByteArrays(sendBuffer, PortTools.intToByte8(h, 1));
sendBuffer = PortTools.concatByteArrays(sendBuffer, PortTools.intToByte8(m, 1));
sendBuffer = PortTools.concatByteArrays(sendBuffer, PortTools.intToByte8(min, 1));
sendBuffer = PortTools.concatByteArrays(sendBuffer, new byte[]{0x00, 0x00});
addSendBuffer(sendBuffer);
}
public void devSearch(int slot) throws LogsIOException {
byte[] sendBuffer = new byte[] {0x02, 0x02, 0x01};
sendBuffer = PortTools.concatByteArrays(sendBuffer, PortTools.intToByte8(slot, 1));
sendBuffer = PortTools.concatByteArrays(sendBuffer, PortTools.intToByte8(0, 1));
sendBuffer = PortTools.concatByteArrays(sendBuffer, PortTools.intToByte8(0, 1));
sendBuffer = PortTools.concatByteArrays(sendBuffer, PortTools.intToByte8(0, 1));
sendBuffer = PortTools.concatByteArrays(sendBuffer, new byte[]{0x00, 0x00});
addSendBuffer(sendBuffer);
}
@Override
protected void close(HandlerMain handlerMain) {
try {
if (this.comPort != null) {
this.comPort.closePort();
}
} catch (LogsIOException e) {
// getLogs().warning(e);
getLogs().warning(e);
}
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
try {
while (isRun() && getCountBySendBuffer() == 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if (isRun() && getCountBySendBuffer() > 0) {
while (isRun() && getCountBySendBuffer() > 0) {
this.comPort.send(getSendBufferByFirst());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
removeSendBufferByFirst();
byte[] readBuffer = this.comPort.readListen(100, 5);
if (readBuffer.length > 0) {
publishReadBuffer(readBuffer);
}
}
}
} catch (LogsIOException e) {
getLogs().warning(e);
}
}
@Override
protected Class<?> setCls() {
return getClass();
}
}

View File

@ -0,0 +1,156 @@
package com.unibuy.smartdevice.controller;
import com.unibuy.smartdevice.MyApp;
import com.unibuy.smartdevice.devices.ComPort;
import com.unibuy.smartdevice.devices.DevNFCPay;
import com.unibuy.smartdevice.devices.PortTools;
import com.unibuy.smartdevice.devices.Rs232Dev;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsParseException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.HandlerMainScheduler;
import java.util.HashMap;
import java.util.Map;
public class DevNFCPayController extends HandlerMainScheduler {
@Override
protected Class<?> setCls() {
return getClass();
}
public enum Option {
TOAST(0),
RESPONSE(5),
;
private int option;
public int getOption() { return option; }
Option(int option) { this.option = option; }
}
private Rs232Dev comPort2;
private DevNFCPay devNFCPay;
public DevNFCPayController(HandlerMain handlerMain) {
super(handlerMain);
try {
comPort2 = new Rs232Dev(MyApp.getInstance().getComPort2ByNFCPay());
devNFCPay = new DevNFCPay(handlerMain.getContext());
} catch (LogsUnsupportedOperationException | LogsIOException e) {
getLogs().warning(e);
}
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
public void start(int payType, int totalPrice) throws LogsIOException {
if (devNFCPay != null) {
clearOldBuffer();
byte[] sendBuffer = devNFCPay.swipe(payType, totalPrice);
String sendData = new String(sendBuffer);
getLogs().info("電文送出:" + sendData);
MyApp.getInstance().getReportFlowInfoData().setFlowSendInfo(sendData);
comPort2.send(sendBuffer);
start();
} else {
throw new LogsIOException(getLogs(), "Dev comport not found");
}
}
private void clearOldBuffer() {
try {
byte[] dummy;
while ((dummy = comPort2.readNonBlocking()) != null && dummy.length > 0) {
getLogs().info("清除舊資料: " + new String(dummy));
}
} catch (Exception e) {
getLogs().info("清空 buffer 發生錯誤: " + e.getMessage());
}
}
@Override
protected void close(HandlerMain handlerMain) {
try {
comPort2.closePort();
} catch (LogsIOException e) {
getLogs().warning(e);
}
}
/*
0000 ? 交易成功
0001 ? 交易失敗 請連絡銀行
0002 ? 交易逾時
0003 ? 操作錯誤
0004 ? 通訊失敗
0005 ? 使用者終止交易
0006 ? 非參加機構卡片
0009 ? 電文錯誤
0010 ? 非聯名卡-客製化參數 075/103 使用
0011 ? 電票金額超過上限
0012 ? 票卡已鎖
0013 ? 無法比對原始電票交易
0014 ? 票卡未開啟自動加值
0015 ? 電票餘額不足
0016 ? 多張票卡讀取失敗
0017 ? 請重新感應卡片
0018 ? 信用卡及電票皆結帳失敗
1001 ? CreditCard settlement is success, 信用卡結帳成功電票結帳失敗
1002 ? CreditCard settlement is failure, 信用卡結帳失敗電票結帳成功
1003 ? CreditCard settlement is failure, 信用卡結帳失敗電票結帳成功
*/
@Override
protected void execute(HandlerMain handlerMain) {
try {
byte[] readBuffer = comPort2.readToMatch(new byte[]{0x03}, 4096);
getLogs().info("readBuffer length:" + readBuffer.length);
if (readBuffer.length != 404) {
getLogs().info("❌ 長度不符,立即中止");
// 讀取長度異常直接結束
reportError("0001", "讀取長度錯誤");
return;
}
comPort2.send(devNFCPay.ok());
String readData = new String(readBuffer);
getLogs().info("電文接收:" + readData);
MyApp.getInstance().getReportFlowInfoData().setFlowRequestInfo(readData);
HashMap<String, String> readMap = devNFCPay.read(readData);
logReadMap(readMap);
String code = readMap.get("code");
if ("0003".equals(code)) {
// 這裡仍可選擇是否要重試依實務需求來看
getLogs().info("操作錯誤 code:0003不重試直接回報錯誤");
reportError("0003", "操作錯誤");
} else {
getLogs().info("交易完成,回傳代碼: " + code);
getHandlerMain().start(getClass().getSimpleName(), Option.RESPONSE.getOption(), code);
}
} catch (LogsParseException | LogsIOException e) {
getLogs().warning(e);
reportError("9999", "例外異常");
}
}
private void reportError(String code, String logMessage) {
getLogs().info("錯誤回報 code: " + code + " 描述: " + logMessage);
getHandlerMain().start(getClass().getSimpleName(), Option.RESPONSE.getOption(), code);
}
private void logReadMap(HashMap<String, String> readMap) {
getLogs().info("======== DevNFCPay parse result ========");
for (Map.Entry<String, String> entry : readMap.entrySet()) {
getLogs().info("Key='" + entry.getKey() + "', Value='" + entry.getValue() + "'");
}
getLogs().info("========================================");
}
}

View File

@ -0,0 +1,337 @@
package com.unibuy.smartdevice.controller;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;
import static com.blankj.utilcode.util.ViewUtils.runOnUiThread;
import com.unibuy.smartdevice.MyApp;
import com.unibuy.smartdevice.devices.DevXinYuan;
import com.unibuy.smartdevice.devices.PortTools;
import com.unibuy.smartdevice.devices.Rs232Dev;
import com.unibuy.smartdevice.exception.ErrorCode;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsParseException;
import com.unibuy.smartdevice.exception.LogsSettingEmptyException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import com.unibuy.smartdevice.external.HttpAPI;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.ui.FontendActivity;
import java.util.HashMap;
import java.util.Map;
public class DevXinYuanController extends DevController {
private Logs logs;
private HttpAPI httpAPI;
private Rs232Dev rs232Dev;
private DevXinYuan devXinYuan;
private static int temperature = 0;
private static String version = "";
public static final Map<Byte, DevXinYuan.VMC> vmcMap = new HashMap<>();
// 靜態區塊初始化 Map
static {
for (DevXinYuan.VMC vmc : DevXinYuan.VMC.values()) {
vmcMap.put(vmc.getBytes()[0], vmc);
}
}
public static int sllloot;
public DevXinYuan getDevXinYuan() {
return devXinYuan;
}
public boolean isConnected() {
return rs232Dev != null && rs232Dev.isPortOpen() && isRun();
}
public DevXinYuanController(HandlerMain handlerMain) {
super( 50, handlerMain);
this.logs = new Logs(getClass());
this.devXinYuan = new DevXinYuan();
try {
this.rs232Dev = new Rs232Dev(MyApp.getInstance().getComPort1ByXinYuan());
devXinYuan.setRun(true);
logs.debug("下位機連接");
} catch (LogsUnsupportedOperationException | LogsIOException e) {
// getLogs().error(ErrorCode.DEV_ERROR, "@下位機連接錯誤", handlerMain);
getLogs().warning(e);
setRun(false);
}
}
@Override
protected void close(HandlerMain handlerMain) {
devXinYuan.setRun(false);
try {
this.rs232Dev.closePort();
} catch (LogsIOException e) {
getLogs().warning(e);
}
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
devXinYuanRun(handlerMain);
}
/**
* Debug helper: simulate VMC_04_BUY_STATUS by sending a fake type to backend.
* This method is self-contained and will delay 2s before sending.
* Usage: simulateVmc04BuyStatus(12, "0402");
*/
public void simulateVmc04BuyStatus(int slot) {
new Thread(() -> {
try {
// optional delay so it doesn't collide with real events
Thread.sleep(5000);
if (httpAPI == null) {
httpAPI = new HttpAPI(getHandlerMain());
}
// runOnUiThread(() -> Toast.makeText(MyApp.getInstance(), "[Fake] 準備送出: slot=" + slot , Toast.LENGTH_SHORT).show());
httpAPI.errorPost(slot, "0402");
// runOnUiThread(() -> Toast.makeText(MyApp.getInstance(), "[Fake] 已送出: slot=" + slot , Toast.LENGTH_SHORT).show());
} catch (InterruptedException ie) {
logs.warning(ie);
} catch (LogsSettingEmptyException | LogsParseException e) {
logs.warning(e);
runOnUiThread(() -> Toast.makeText(MyApp.getInstance(), "[Fake] 發送失敗: " + e.getMessage(), Toast.LENGTH_LONG).show());
} catch (Exception e) {
logs.warning(e);
runOnUiThread(() -> Toast.makeText(MyApp.getInstance(), "[Fake] 例外: " + e.getClass().getSimpleName(), Toast.LENGTH_LONG).show());
}
}).start();
}
public void devXinYuanRun(HandlerMain handlerMain) {
while (isRun()) {
try {
byte[] stx = rs232Dev.readToMatch(DevXinYuan.VMC.VMC_FAFB_STX.getBytes(), 0);
getLogs().debug("leng:" + stx.length + " buffer:" + PortTools.showHex(stx));
byte[] vmcCmd = new byte[2];
rs232Dev.read(vmcCmd);
byte[] vmcData = new byte[vmcCmd.length==2?vmcCmd[1]:0];
rs232Dev.read(vmcData);
byte[] vmcXor = new byte[1];
rs232Dev.read(vmcXor);
Byte key = Byte.valueOf(vmcCmd[0]);
if (!vmcMap.containsKey(key)) {
getLogs().info("XinYuan vmcCmd:" + PortTools.showHex(vmcCmd));
getLogs().info("XinYuan vmcData:" + PortTools.showHex(vmcData));
getLogs().info("XinYuan vmcXor:" + PortTools.showHex(vmcXor));
getLogs().info("XinYuan vmc not found");
continue;
}
DevXinYuan.VMC vmc = vmcMap.get(key);
if (vmc != DevXinYuan.VMC.VMC_41_POLL) {
getLogs().info("XinYuan vmcCmd:" + PortTools.showHex(vmcCmd));
getLogs().info("XinYuan vmcData:" + PortTools.showHex(vmcData));
getLogs().info("XinYuan vmcXor:" + PortTools.showHex(vmcXor));
getLogs().info("XinYuan vmc:" + vmc.name());
}
switch (vmc) {
case VMC_41_POLL:
if (getCountBySendBuffer() > 0) {
byte[] cmdBytes = getSendBufferByFirst();
getLogs().info("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"+bytesToHex(cmdBytes));
if (cmdBytes.length == (4+cmdBytes[3]+1)) {
for (int sendCount=1; sendCount <2; sendCount++) {
rs232Dev.send(cmdBytes);
getLogs().info("XinYuan Send:" + PortTools.showHex(cmdBytes));
byte[] vmcBuffer = rs232Dev.readListen(0, 1);
if (vmcBuffer.length > 2) {
key = Byte.valueOf(vmcBuffer[2]);
if (vmcMap.containsKey(key)) {
vmc = vmcMap.get(key);
if (vmc == null) continue;
switch (vmc) {
case VMC_42_ACK:
publishReadBuffer(vmc.getBytes());
break;
}
}
}
}
} else {
logs.debug("cmd length error:"+PortTools.showHex(cmdBytes));
logs.clearMessage();
}
removeSendBufferByFirst();
} else {
rs232Dev.send(devXinYuan.sendACKByIsShow(false));
}
break;
case VMC_02_CHECK_SLOT_STATUS:
publishReadBuffer(PortTools.concatByteArrays(vmcCmd[0], vmcData[1]));
rs232Dev.send(devXinYuan.sendACK());
break;
case VMC_04_BUY_STATUS:
new Thread(() -> {
try {
if (httpAPI == null) httpAPI = new HttpAPI(getHandlerMain());
int slot = ((vmcData[2] & 0xFF) << 8) | (vmcData[3] & 0xFF);
// String statusMessage = PortTools.showHex(new byte[]{vmcCmd[0],vmcData[1]}).replace(" ", "");
String statusMessage = String.format("%02X%02X", vmcCmd[0] & 0xFF, vmcData[1] & 0xFF);
// runOnUiThread(() ->
// Toast.makeText(MyApp.getInstance(), "傳送訊息"+statusMessage, Toast.LENGTH_LONG).show()
// );
//最後一筆0402得到貨道是0可能覆蓋 //所以抓取前面三筆出貨前的資料
if(slot>0){
sllloot= slot;
}
//放這邊因為最後一筆 出貨成功跟微波爐請取餐 可能排成造成的無法傳送API後台
//也許原因是因為速度過快覆蓋 所以而外拉出來一個方法來處理 0402
if(statusMessage.equals("0402")){
simulateVmc04BuyStatus(sllloot);
}
httpAPI.errorPost(slot, statusMessage);
logs.info("VMC_04_BUY_STATUS errorPost sent.");
} catch (LogsSettingEmptyException | LogsParseException e) {
logs.warning(e);
runOnUiThread(() ->
Toast.makeText(MyApp.getInstance(), "錯誤: " + e.getMessage(), Toast.LENGTH_SHORT).show()
);
} catch (Exception e) {
logs.warning(e); // 不再丟出 RuntimeException
}
}).start();
/// ////////////////
publishReadBuffer(PortTools.concatByteArrays(vmcCmd[0], vmcData[1]));
rs232Dev.send(devXinYuan.sendACK());
break;
case VMC_38_GIVE_CHANGE_MODE:
publishReadBuffer(PortTools.concatByteArrays(vmcCmd[0], vmcData[1]));
rs232Dev.send(devXinYuan.sendACK());
break;
case VMC_21_GET_MONEY:
int number21 = PortTools.byte8ToInt(vmcData[2], vmcData[3], vmcData[4], vmcData[5])/100;
publishReadBuffer(PortTools.concatByteArrays(vmcCmd[0], vmcData[1]), PortTools.intToByte8(number21, 2));
rs232Dev.send(devXinYuan.sendACK());
break;
case VMC_23_NOW_GET_TOTAL:
int number23 = PortTools.byte8ToInt(vmcData[1], vmcData[2], vmcData[3], vmcData[4])/100;
publishReadBuffer(PortTools.concatByteArrays(vmcCmd[0], (byte)0x00), PortTools.intToByte8(number23, 2));
rs232Dev.send(devXinYuan.sendACK());
break;
case VMC_26_GIVE_CHANGE:
int bill26 = PortTools.byte8ToInt(vmcData[1], vmcData[2], vmcData[3], vmcData[4])/100;
int coin26 = PortTools.byte8ToInt(vmcData[5], vmcData[6], vmcData[7], vmcData[8])/100;
int number26 = bill26 + coin26;
publishReadBuffer(PortTools.concatByteArrays(vmcCmd[0], (byte)0x00), PortTools.intToByte8(number26, 2));
rs232Dev.send(devXinYuan.sendACK());
break;
case VMC_27_IN_COME:
int number27 = PortTools.byte8ToInt(vmcData[1], vmcData[2], vmcData[3], vmcData[4])/100;
publishReadBuffer(PortTools.concatByteArrays(vmcCmd[0], (byte)0x00), PortTools.intToByte8(number27, 2));
rs232Dev.send(devXinYuan.sendACK());
break;
case VMC_29_MONEY_SWITCH:
publishReadBuffer(PortTools.concatByteArrays(vmcCmd[0], vmcData[1]));
rs232Dev.send(devXinYuan.sendACK());
break;
case VMC_31_SYNC_PACK_NO:
publishReadBuffer(PortTools.concatByteArrays(vmcCmd[0], vmcData[0]));
rs232Dev.send(devXinYuan.sendACK());
break;
case VMC_32_GET_VERSION:
publishReadBuffer(PortTools.concatByteArrays(vmcCmd[0], vmcData[1]));
rs232Dev.send(devXinYuan.sendACK());
break;
case VMC_52_CHECK_VMC_STATUS:
//溫度:vmcData[7]
getLogs().info("下位機訊號"+PortTools.showHex(vmcData));
if (PortTools.showHex(vmcData).isEmpty()) {
getLogs().info("下位機失連重啟APP");
Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> {
Context context = MyApp.getInstance().getApplicationContext();
Intent intent = new Intent(context, FontendActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
android.os.Process.killProcess(android.os.Process.myPid());
});
}
DevXinYuanController.setTemperature(vmcData[5]);
rs232Dev.send(devXinYuan.sendACK());
break;
default:
rs232Dev.send(devXinYuan.sendACK());
}
} catch (LogsIOException e) {
getLogs().warning(e);
}
}
}
public static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X ", b));
}
return sb.toString().trim();
}
@Override
protected Class<?> setCls() {
return getClass();
}
@Override
protected String description() {
return getClass().getSimpleName();
}
public static int getTemperature() {
return temperature;
}
public static void setTemperature(int temperature) {
DevXinYuanController.temperature = temperature;
}
public static String getVersion() {
return version;
}
public static void setVersion(String version) {
DevXinYuanController.version = version;
}
}

View File

@ -0,0 +1,49 @@
package com.unibuy.smartdevice.controller;
import com.unibuy.smartdevice.devices.ComPort;
import com.unibuy.smartdevice.devices.Rs232Dev;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import com.unibuy.smartdevice.tools.HandlerMain;
public class UseAllComPortSendController extends DevController {
private Logs logs;
public UseAllComPortSendController(HandlerMain handlerMain) {
super( 20, handlerMain);
this.logs = new Logs(getClass());
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void execute(HandlerMain handlerMain) {
try {
Rs232Dev rs232Dev = new Rs232Dev();
for (ComPort comPort : ComPort.values()) {
logs.info("connect:" + comPort.getFilepath());
rs232Dev.connectPort(comPort);
for(int index=0; index<getCountBySendBuffer(); index++) {
rs232Dev.send(getSendBuffer(index));
Thread.sleep(100);
}
rs232Dev.closePort();
Thread.sleep(1000);
}
} catch (LogsUnsupportedOperationException | LogsIOException e) {
// getLogs().warning(e);
getLogs().warning(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
protected Class<?> setCls() {
return getClass();
}
}

View File

@ -0,0 +1,310 @@
package com.unibuy.smartdevice.database;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "mydata.db";
private static final int DATABASE_VERSION = 1;
public enum column {
COLUMN_ID("INTEGER PRIMARY KEY");
private String type;
column(String type) {
this.type = type;
}
public String getType() {
return type;
}
public String getName() {
if (this.name().equals("TABLE")) {
int index = this.getClass().getName().indexOf('$');
return this.getClass().getName().substring(index + 1);
} else {
return this.name().toLowerCase();
}
}
public String getCreateSQL(String end) {
if (this.name().equals("TABLE")) {
return this.getName() + end;
} else {
return this.name().toLowerCase() + " " + getType() + end;
}
}
}
public enum settinglogs {
TABLE("settinglogs"),
STATUS("TEXT NOT NULL")
;
private String type;
settinglogs(String type) {
this.type = type;
}
public String getType() {
return type;
}
public String getName() {
if (this.name().equals("TABLE")) {
return this.getType();
} else {
return this.name().toLowerCase();
}
}
public String getCreateSQL(String end) {
if (this.name().equals("TABLE")) {
return this.getName() + end;
} else {
return this.name().toLowerCase() + " " + getType() + end;
}
}
}
public enum settings {
TABLE("settings"),
SETTING_ID("TEXT NOT NULL"),
DATA1("TEXT"),
DATA2("TEXT"),
DATA3("TEXT"),
DATA4("TEXT"),
DATA5("TEXT"),
DATA6("TEXT"),
DATA7("TEXT"),
DATA8("TEXT"),
DATA9("TEXT"),
DATA10("TEXT")
;
private String type;
settings(String type) {
this.type = type;
}
public String getType() {
return type;
}
public String getName() {
if (this.name().equals("TABLE")) {
return this.getType();
} else {
return this.name().toLowerCase();
}
}
public String getCreateSQL(String end) {
if (this.name().equals("TABLE")) {
return this.getName() + end;
} else {
return this.name().toLowerCase() + " " + getType() + end;
}
}
}
public enum products {
TABLE("products"),
PRODUCT_ID("TEXT NOT NULL"),
PRODUCT_IMG("TEXT NOT NULL"),
PRODUCT_NAME("TEXT NOT NULL"),
MACHINE_PRICE("INTEGER NOT NULL"),
SELLING_PRICE("INTEGER NOT NULL"),
MEMBER_PRICE("INTEGER NOT NULL"),
SLOT_UPPER_LIMIT("INTEGER NOT NULL"),
MARKETING_PLAN("TEXT NOT NULL"),
MATERIAL_CODE("TEXT NOT NULL"),
PRODUCT_NAME_EN("TEXT NOT NULL"),
PRODUCT_NAME_JP("TEXT NOT NULL")
;
private String type;
products(String type) {
this.type = type;
}
public String getType() {
return type;
}
public String getName() {
if (this.name().equals("TABLE")) {
return this.getType();
} else {
return this.name().toLowerCase();
}
}
public String getCreateSQL(String end) {
if (this.name().equals("TABLE")) {
return this.getName() + end;
} else {
return this.name().toLowerCase() + " " + getType() + end;
}
}
}
/*
this.slot = slot;
this.product = product;
this.count = count;
this.lock = false;
*/
public enum slot {
TABLE("slot"),
FIELD("TEXT NOT NULL"),
SLOT("INTEGER NOT NULL"),
PRODUCT_ID("TEXT NOT NULL"),
COUNT("INTEGER NOT NULL"),
LOCK("TINYINT NOT NULL"),
OTHER_DATA("TEXT"),
;
private String type;
slot(String type) {
this.type = type;
}
public String getType() {
return type;
}
public String getName() {
if (this.name().equals("TABLE")) {
return this.getType();
} else {
return this.name().toLowerCase();
}
}
public String getCreateSQL(String end) {
if (this.name().equals("TABLE")) {
return this.getName() + end;
} else {
return this.name().toLowerCase() + " " + getType() + end;
}
}
}
public enum memo {
TABLE("memo"),
FIELD("TEXT NOT NULL"),
DATA("TEXT NOT NULL"),
OTHER_DATA("TEXT"),
;
private String type;
memo(String type) {
this.type = type;
}
public String getType() {
return type;
}
public String getName() {
if (this.name().equals("TABLE")) {
return this.getType();
} else {
return this.name().toLowerCase();
}
}
public String getCreateSQL(String end) {
if (this.name().equals("TABLE")) {
return this.getName() + end;
} else {
return this.name().toLowerCase() + " " + getType() + end;
}
}
}
// 建表語句
private static final String CREATE_TABLE_SETTINGLOGS =
"CREATE TABLE " + settinglogs.TABLE.getCreateSQL("(") +
column.COLUMN_ID.getCreateSQL(", ") +
settinglogs.STATUS.getCreateSQL(");");
private static final String CREATE_TABLE_SETTINGS =
"CREATE TABLE " + settings.TABLE.getCreateSQL("(") +
column.COLUMN_ID.getCreateSQL(", ") +
settings.SETTING_ID.getCreateSQL(", ") +
settings.DATA1.getCreateSQL(", ") +
settings.DATA2.getCreateSQL(", ") +
settings.DATA3.getCreateSQL(", ") +
settings.DATA4.getCreateSQL(", ") +
settings.DATA5.getCreateSQL(", ") +
settings.DATA6.getCreateSQL(", ") +
settings.DATA7.getCreateSQL(", ") +
settings.DATA8.getCreateSQL(", ") +
settings.DATA9.getCreateSQL(", ") +
settings.DATA10.getCreateSQL(");");
private static final String CREATE_TABLE_PRODUCTS =
"CREATE TABLE " + products.TABLE.getCreateSQL("(") +
column.COLUMN_ID.getCreateSQL(", ") +
products.PRODUCT_ID.getCreateSQL(", ") +
products.PRODUCT_IMG.getCreateSQL(", ") +
products.PRODUCT_NAME.getCreateSQL(", ") +
products.MACHINE_PRICE.getCreateSQL(", ") +
products.SELLING_PRICE.getCreateSQL(", ") +
products.MEMBER_PRICE.getCreateSQL(", ") +
products.SLOT_UPPER_LIMIT.getCreateSQL(", ") +
products.MARKETING_PLAN.getCreateSQL(", ") +
products.MATERIAL_CODE.getCreateSQL(", ") +
products.PRODUCT_NAME_EN.getCreateSQL(", ") +
products.PRODUCT_NAME_JP.getCreateSQL(");");
private static final String CREATE_TABLE_SLOT =
"CREATE TABLE " + slot.TABLE.getCreateSQL("(") +
column.COLUMN_ID.getCreateSQL(", ") +
slot.FIELD.getCreateSQL(", ") +
slot.SLOT.getCreateSQL(", ") +
slot.PRODUCT_ID.getCreateSQL(", ") +
slot.COUNT.getCreateSQL(", ") +
slot.LOCK.getCreateSQL(", ") +
slot.OTHER_DATA.getCreateSQL(");")
;
private static final String CREATE_TABLE_MEMO =
"CREATE TABLE " + memo.TABLE.getCreateSQL("(") +
column.COLUMN_ID.getCreateSQL(", ") +
memo.FIELD.getCreateSQL(", ") +
memo.DATA.getCreateSQL(", ") +
memo.OTHER_DATA.getCreateSQL(");")
;
public void exec(SQLiteDatabase db, String sqlString) {
Log.i("", "sqlString:" + sqlString);
db.execSQL(sqlString);
}
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
exec(db, CREATE_TABLE_SETTINGLOGS);
exec(db, CREATE_TABLE_SETTINGS);
exec(db, CREATE_TABLE_PRODUCTS);
exec(db, CREATE_TABLE_SLOT);
exec(db, CREATE_TABLE_MEMO);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
exec(db, "DROP TABLE IF EXISTS " + settinglogs.TABLE.getName());
exec(db, "DROP TABLE IF EXISTS " + settings.TABLE.getName());
exec(db, "DROP TABLE IF EXISTS " + products.TABLE.getName());
exec(db, "DROP TABLE IF EXISTS " + slot.TABLE.getName());
exec(db, "DROP TABLE IF EXISTS " + memo.TABLE.getName());
onCreate(db);
}
}

View File

@ -0,0 +1,174 @@
package com.unibuy.smartdevice.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.unibuy.smartdevice.MyApp;
import com.unibuy.smartdevice.devices.SlotField;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsNoSuchElementException;
import com.unibuy.smartdevice.structure.MemoStructure;
import com.unibuy.smartdevice.structure.ProductStructure;
import com.unibuy.smartdevice.structure.SlotStructure;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MemoDao {
private Logs logs;
private Map<String, List<MemoStructure>> memoMap;
private final SQLiteDatabase database;
public MemoDao(Context context) {
logs = new Logs(this.getClass());
DatabaseHelper dbHelper = new DatabaseHelper(context);
database = dbHelper.getWritableDatabase();
mapUpdate();
}
public void mapUpdate() {
memoMap = getAll();
}
public void insertOnlyOne(MemoStructure data) {
deleteField(data.getField());
insertOne(data);
logs.info("insertOnlyOne:" + data.toString());
}
// 插入單一 Product
public void insertOne(MemoStructure data) {
ContentValues values = new ContentValues();
values.put(DatabaseHelper.memo.FIELD.getName(), data.getField());
values.put(DatabaseHelper.memo.DATA.getName(), data.getData().toString());
values.put(DatabaseHelper.memo.OTHER_DATA.getName(), data.getOtherData().toString());
logs.info("insertOne:" + values.toString());
long result = database.insert(DatabaseHelper.memo.TABLE.getName(), null, values);
logs.info("insertOne result:" + result);
}
// 批量插入 Products
public void insertAll(Map<String, List<MemoStructure>> memoMap) {
if (memoMap.size() == 0) {
return;
}
database.beginTransaction();
try {
for(String key: memoMap.keySet()) {
List<MemoStructure> memoList = memoMap.get(key);
for (MemoStructure data : memoList) {
insertOne(data);
}
}
database.setTransactionSuccessful();
} finally {
database.endTransaction();
}
}
public Map<String, List<MemoStructure>> getMemoData() {
return memoMap;
}
public List<MemoStructure> getList(String field) {
if (memoMap.containsKey(field)) {
logs.debug("containsKey:" + field);
return memoMap.get(field);
} else {
logs.debug("no fund:" + field);
return new ArrayList<>();
}
}
public int getCount(String field) {
int size = getList(field).size();
logs.debug("getCount size:" + size);
return size;
}
public boolean existOnlyOne(String field) {
int size = getCount(field);
logs.debug("existOnlyOne size:" + size);
return size == 1;
}
public MemoStructure getOnlyOne(String field) {
return getList(field).get(0);
}
// 獲取所有 Products
private Map<String, List<MemoStructure>> getAll() {
Map<String, List<MemoStructure>> memoMap = new HashMap<>();
Cursor cursor = database.query(
DatabaseHelper.memo.TABLE.getName(),
null, // 全部欄位
null, // 無條件
null,
null,
null,
null);
if (cursor != null) {
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.column.COLUMN_ID.getName()));
String field = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.memo.FIELD.getName()));
String data = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.memo.DATA.getName()));
String otherData = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.memo.OTHER_DATA.getName()));
JSONObject dataByJsonObject;
try {
dataByJsonObject = new JSONObject(data);
} catch (JSONException e) {
dataByJsonObject = new JSONObject();
}
JSONObject otherDataByJsonObject;
try {
otherDataByJsonObject = new JSONObject(otherData);
} catch (JSONException e) {
otherDataByJsonObject = new JSONObject();
}
if (!memoMap.containsKey(field)) {
memoMap.put(field, new ArrayList<>());
}
MemoStructure memoData = new MemoStructure(field, dataByJsonObject, otherDataByJsonObject);
memoMap.get(field).add(memoData);
}
cursor.close();
}
logs.debug("getAll:" + memoMap.toString());
return memoMap;
}
// 刪除所有 Products
public void deleteAll() {
database.delete(DatabaseHelper.memo.TABLE.getName(), null, null);
}
public void deleteField(String field) {
logs.debug("delete:\""+DatabaseHelper.memo.FIELD.getName() + "\"="+field);
database.delete(DatabaseHelper.memo.TABLE.getName(), "\""+DatabaseHelper.memo.FIELD.getName() + "\"=?", new String[]{field});
}
// 關閉資料庫
public void close() {
database.close();
}
}

View File

@ -0,0 +1,95 @@
package com.unibuy.smartdevice.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.unibuy.smartdevice.structure.ProductStructure;
import java.util.ArrayList;
import java.util.List;
public class ProductsDao {
private final SQLiteDatabase database;
public ProductsDao(Context context) {
DatabaseHelper dbHelper = new DatabaseHelper(context);
database = dbHelper.getWritableDatabase();
}
// 插入單一 Product
public void insertOne(ProductStructure data) {
ContentValues values = new ContentValues();
values.put(DatabaseHelper.products.PRODUCT_ID.getName(), data.getProductID());
values.put(DatabaseHelper.products.PRODUCT_IMG.getName(), data.getProductImg());
values.put(DatabaseHelper.products.PRODUCT_NAME.getName(), data.getProductName());
values.put(DatabaseHelper.products.MACHINE_PRICE.getName(), data.getMachinePrice());
values.put(DatabaseHelper.products.SELLING_PRICE.getName(), data.getSellingPrice());
values.put(DatabaseHelper.products.MEMBER_PRICE.getName(), data.getMemberPrice());
values.put(DatabaseHelper.products.SLOT_UPPER_LIMIT.getName(), data.getSlotUpperLimit());
values.put(DatabaseHelper.products.MARKETING_PLAN.getName(), data.getMarketingPlan());
values.put(DatabaseHelper.products.MATERIAL_CODE.getName(), data.getMaterialCode());
values.put(DatabaseHelper.products.PRODUCT_NAME_EN.getName(), data.getProductNameEn());
values.put(DatabaseHelper.products.PRODUCT_NAME_JP.getName(), data.getProductNameJp());
long index = database.insert(DatabaseHelper.products.TABLE.getName(), null, values);
Log.i("database insert", "插入第"+index+"資料:"+values.toString());
}
// 批量插入 Products
public void insertAll(List<ProductStructure> list) {
database.beginTransaction();
try {
for (ProductStructure data : list) {
insertOne(data);
}
database.setTransactionSuccessful();
} finally {
database.endTransaction();
}
}
// 獲取所有 Products
public List<ProductStructure> getAll() {
List<ProductStructure> list = new ArrayList<>();
Cursor cursor = database.query(
DatabaseHelper.products.TABLE.getName(),
null, // 全部欄位
null, // 無條件
null,
null,
null,
null);
if (cursor != null) {
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.column.COLUMN_ID.getName()));
String productId = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.products.PRODUCT_ID.getName()));
String productImg = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.products.PRODUCT_IMG.getName()));
String productName = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.products.PRODUCT_NAME.getName()));
int machingPrice = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.products.MACHINE_PRICE.getName()));
int sellingPrice = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.products.SELLING_PRICE.getName()));
int memberPrice = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.products.MEMBER_PRICE.getName()));
int slotUpperLimit = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.products.SLOT_UPPER_LIMIT.getName()));
String marketingPlan = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.products.MARKETING_PLAN.getName()));;
String materialCode = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.products.MATERIAL_CODE.getName()));;
String productNameEn = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.products.PRODUCT_NAME_EN.getName()));
String productNameJp = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.products.PRODUCT_NAME_JP.getName()));
list.add(new ProductStructure(productId, productImg, productName, machingPrice,sellingPrice,memberPrice,slotUpperLimit,marketingPlan,materialCode,productNameEn,productNameJp));
}
cursor.close();
}
return list;
}
// 刪除所有 Products
public void deleteAll() {
database.delete(DatabaseHelper.products.TABLE.getName(), null, null);
}
// 關閉資料庫
public void close() {
database.close();
}
}

View File

@ -0,0 +1,79 @@
package com.unibuy.smartdevice.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.structure.SettingStructure;
import java.util.ArrayList;
import java.util.List;
public class SettinglogsDao {
private Logs logs;
private final SQLiteDatabase database;
public SettinglogsDao(Context context) {
logs = new Logs(getClass());
DatabaseHelper dbHelper = new DatabaseHelper(context);
database = dbHelper.getWritableDatabase();
}
// 插入單一 Product
public void insertOne(String data) {
ContentValues values = new ContentValues();
values.put(DatabaseHelper.settinglogs.STATUS.getName(), data);
long index = database.insert(DatabaseHelper.settinglogs.TABLE.getName(), null, values);
logs.info("插入第"+index+"資料:"+values.toString());
}
// 批量插入 Products
public void insertAll(List<String> list) {
database.beginTransaction();
try {
for (String data : list) {
insertOne(data);
}
database.setTransactionSuccessful();
} finally {
database.endTransaction();
}
}
// 獲取所有 Products
public List<String> getAll() {
List<String> list = new ArrayList<>();
Cursor cursor = database.query(
DatabaseHelper.settinglogs.TABLE.getName(),
null, // 全部欄位
null, // 無條件
null,
null,
null,
null);
if (cursor != null) {
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.column.COLUMN_ID.getName()));
String status = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settinglogs.STATUS.getName()));
list.add(status);
}
cursor.close();
}
Log.i("SettinglogsDaoGetAll", "count:"+list.size());
return list;
}
// 刪除所有 Products
public void deleteAll() {
database.delete(DatabaseHelper.settinglogs.TABLE.getName(), null, null);
}
// 關閉資料庫
public void close() {
database.close();
}
}

View File

@ -0,0 +1,154 @@
package com.unibuy.smartdevice.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.structure.ProductStructure;
import com.unibuy.smartdevice.structure.SettingStructure;
import java.util.ArrayList;
import java.util.List;
public class SettingsDao {
private Logs logs;
private final SQLiteDatabase database;
public SettingsDao(Context context) {
logs = new Logs(getClass());
DatabaseHelper dbHelper = new DatabaseHelper(context);
database = dbHelper.getWritableDatabase();
}
public void insertOne(SettingStructure data) {
logs.debug("insertOne data:" + data.toString());
ContentValues values = new ContentValues();
values.put(DatabaseHelper.settings.SETTING_ID.getName(), data.getSettingId());
if (data.getDataCount() >= 1 && data.getData(0) != null && !data.getData(0).isEmpty()) values.put(DatabaseHelper.settings.DATA1.getName(), data.getData(0));
if (data.getDataCount() >= 2 && data.getData(1) != null && !data.getData(1).isEmpty()) values.put(DatabaseHelper.settings.DATA2.getName(), data.getData(1));
if (data.getDataCount() >= 3 && data.getData(2) != null && !data.getData(2).isEmpty()) values.put(DatabaseHelper.settings.DATA3.getName(), data.getData(2));
if (data.getDataCount() >= 4 && data.getData(3) != null && !data.getData(3).isEmpty()) values.put(DatabaseHelper.settings.DATA4.getName(), data.getData(3));
if (data.getDataCount() >= 5 && data.getData(4) != null && !data.getData(4).isEmpty()) values.put(DatabaseHelper.settings.DATA5.getName(), data.getData(4));
if (data.getDataCount() >= 6 && data.getData(5) != null && !data.getData(5).isEmpty()) values.put(DatabaseHelper.settings.DATA6.getName(), data.getData(5));
if (data.getDataCount() >= 7 && data.getData(6) != null && !data.getData(6).isEmpty()) values.put(DatabaseHelper.settings.DATA7.getName(), data.getData(6));
if (data.getDataCount() >= 8 && data.getData(7) != null && !data.getData(7).isEmpty()) values.put(DatabaseHelper.settings.DATA8.getName(), data.getData(7));
if (data.getDataCount() >= 9 && data.getData(8) != null && !data.getData(8).isEmpty()) values.put(DatabaseHelper.settings.DATA9.getName(), data.getData(8));
if (data.getDataCount() >= 10 && data.getData(9) != null && !data.getData(9).isEmpty()) values.put(DatabaseHelper.settings.DATA10.getName(), data.getData(9));
long index = database.insert(DatabaseHelper.settings.TABLE.getName(), null, values);
Log.i("database insert", "插入第"+index+"資料:"+values.toString());
}
// 批量插入 Products
public void insertAll(List<SettingStructure> list) {
database.beginTransaction();
try {
for (SettingStructure data : list) {
insertOne(data);
}
database.setTransactionSuccessful();
} finally {
database.endTransaction();
}
}
// 獲取所有 Products
public List<SettingStructure> getAll() {
List<SettingStructure> list = new ArrayList<>();
Cursor cursor = database.query(
DatabaseHelper.settings.TABLE.getName(),
null, // 全部欄位
null, // 無條件
null,
null,
null,
null);
if (cursor != null) {
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.column.COLUMN_ID.getName()));
String settingId = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.SETTING_ID.getName()));
String data1 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA1.getName()));
String data2 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA2.getName()));
String data3 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA3.getName()));
String data4 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA4.getName()));
String data5 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA5.getName()));
String data6 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA6.getName()));
String data7 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA7.getName()));
String data8 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA8.getName()));
String data9 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA9.getName()));
String data10 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA10.getName()));
list.add(new SettingStructure(settingId, new String[]{data1, data2, data3, data4, data5, data6, data7, data8, data9, data10}));
}
cursor.close();
}
Log.i("SettingsDaoGetAll", "count:"+list.size());
return list;
}
public List<SettingStructure> getWhere(String whereSettingId) {
List<SettingStructure> list = new ArrayList<>();
Cursor cursor = database.query(
DatabaseHelper.settings.TABLE.getName(),
null, // 全部欄位
DatabaseHelper.settings.SETTING_ID.getName()+"=?", // 無條件
new String[] {whereSettingId},
null,
null,
null);
if (cursor != null) {
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.column.COLUMN_ID.getName()));
String settingId = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.SETTING_ID.getName()));
String data1 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA1.getName()));
String data2 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA2.getName()));
String data3 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA3.getName()));
String data4 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA4.getName()));
String data5 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA5.getName()));
String data6 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA6.getName()));
String data7 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA7.getName()));
String data8 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA8.getName()));
String data9 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA9.getName()));
String data10 = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.settings.DATA10.getName()));
list.add(new SettingStructure(settingId, new String[]{data1, data2, data3, data4, data5, data6, data7, data8, data9, data10}));
}
cursor.close();
}
Log.i("SettingsDaoGetWhere", "count:"+list.size());
return list;
}
public int getCount(String whereSettingId) {
List<SettingStructure> list = getWhere(whereSettingId);
if (list.isEmpty()) {
return 0;
}
return list.size();
}
public SettingStructure getOne(String whereSettingId) {
List<SettingStructure> list = getWhere(whereSettingId);
if (list.isEmpty()) {
return new SettingStructure(whereSettingId, new String[]{});
}
return list.get(0);
}
public void deleteWhere(String whereSettingId) {
database.delete(DatabaseHelper.settings.TABLE.getName(), DatabaseHelper.settings.SETTING_ID.getName()+"=?", new String[] {whereSettingId});
}
// 刪除所有 Products
public void deleteAll() {
database.delete(DatabaseHelper.settings.TABLE.getName(), null, null);
}
// 關閉資料庫
public void close() {
database.close();
}
}

View File

@ -0,0 +1,138 @@
package com.unibuy.smartdevice.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.unibuy.smartdevice.MyApp;
import com.unibuy.smartdevice.devices.SlotField;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsNoSuchElementException;
import com.unibuy.smartdevice.structure.ProductStructure;
import com.unibuy.smartdevice.structure.SlotStructure;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SlotsDao {
private Logs logs;
private final SQLiteDatabase database;
public SlotsDao(Context context) {
logs = new Logs(this.getClass());
DatabaseHelper dbHelper = new DatabaseHelper(context);
database = dbHelper.getWritableDatabase();
}
// 插入單一 Product
public void insertOne(SlotStructure data) {
ContentValues values = new ContentValues();
values.put(DatabaseHelper.slot.FIELD.getName(), data.getField());
values.put(DatabaseHelper.slot.SLOT.getName(), data.getSlot());
values.put(DatabaseHelper.slot.PRODUCT_ID.getName(), data.getProduct().getProductID());
values.put(DatabaseHelper.slot.COUNT.getName(), data.getCount());
values.put(DatabaseHelper.slot.LOCK.getName(), data.isLock());
values.put(DatabaseHelper.slot.OTHER_DATA.getName(), data.getOtherData().toString());
database.insert(DatabaseHelper.slot.TABLE.getName(), null, values);
}
// 更新指定 field slot 的數量count
public void updateCount(int field, int slot, int newCount) {
ContentValues values = new ContentValues();
values.put(DatabaseHelper.slot.COUNT.getName(), newCount);
String whereClause = DatabaseHelper.slot.FIELD.getName() + "=? AND " + DatabaseHelper.slot.SLOT.getName() + "=?";
String[] whereArgs = { String.valueOf(field), String.valueOf(slot) };
database.update(DatabaseHelper.slot.TABLE.getName(), values, whereClause, whereArgs);
}
// 批量插入 Products
public void insertAll(Map<Integer, List<SlotStructure>> slotMap) {
if (slotMap.size() == 0) {
return;
}
database.beginTransaction();
try {
for(SlotField slotField: SlotField.values()) {
if (slotMap.containsKey(slotField.getField())) {
List<SlotStructure> slotList = slotMap.get(slotField.getField());
for (SlotStructure data : slotList) {
insertOne(data);
}
}
}
database.setTransactionSuccessful();
} finally {
database.endTransaction();
}
}
// 獲取所有 Products
public Map<Integer, List<SlotStructure>> getAll() {
Map<Integer, List<SlotStructure>> slotMap = new HashMap<>();
Cursor cursor = database.query(
DatabaseHelper.slot.TABLE.getName(),
null, // 全部欄位
null, // 無條件
null,
null,
null,
null);
if (cursor != null) {
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.column.COLUMN_ID.getName()));
int field = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.slot.FIELD.getName()));
int slot = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.slot.SLOT.getName()));
String productId = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.slot.PRODUCT_ID.getName()));
int count = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.slot.COUNT.getName()));
boolean lock = cursor.getInt(cursor.getColumnIndexOrThrow(DatabaseHelper.slot.LOCK.getName())) == 1;
String otherData = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.slot.OTHER_DATA.getName()));
JSONObject jsonObject = new JSONObject();
try {
jsonObject = new JSONObject(otherData);
} catch (JSONException e) {}
ProductStructure product = null;
try {
product = MyApp.getInstance().getProduct(productId);
} catch (LogsNoSuchElementException e) {
product = new ProductStructure("?", "","",0,0,0,8, "", "","","");
}
if (!slotMap.containsKey(field)) {
slotMap.put(field, new ArrayList<>());
}
slotMap.get(field).add(new SlotStructure(field, slot, product, count, lock, jsonObject));
}
cursor.close();
}
return slotMap;
}
// 刪除所有 Products
public void deleteAll() {
database.delete(DatabaseHelper.slot.TABLE.getName(), null, null);
}
// 關閉資料庫
public void close() {
database.close();
}
}

View File

@ -0,0 +1,68 @@
package com.unibuy.smartdevice.devices;
import java.util.ArrayList;
import java.util.List;
/*
filepath:/dev/ttymxc1
baudRate:9600
filepath:/dev/ttymxc2
baudRate:9600
filepath:/dev/ttymxc3
baudRate:9600
*/
public enum ComPort {
//57600, N, 8, 1
COM_PORT_1("/dev/ttymxc1", 57600, DeviceType.XINYUAN),
COM_PORT_S1("/dev/ttyS7", 57600, DeviceType.XINYUAN),
COM_PORT_2("/dev/ttymxc2", 9600, DeviceType.NFC_SCANNER),
COM_PORT_S2("/dev/ttyS6", 9600, DeviceType.NFC_SCANNER),
COM_PORT_3("/dev/ttymxc3", 38400, DeviceType.ELECTRIC),
COM_PORT_4("/dev/ttymxc4", 38400, DeviceType.UNKNOWN),
COM_PORT_5("/dev/ttymxc5", 38400, DeviceType.UNKNOWN),
COM_PORT_6("/dev/ttymxc6", 38400, DeviceType.DIGITAL_DISPLAY),
COM_PORT_7("/dev/ttymxc7", 38400, DeviceType.UNKNOWN);
private final String filepath;
private final int baudRate;
private final DeviceType deviceType;
// 靜態篩選方法
public static List<ComPort> getPortsByDeviceType(DeviceType type) {
List<ComPort> result = new ArrayList<>();
for (ComPort port : ComPort.values()) {
if (port.getDeviceType() == type) {
result.add(port);
}
}
return result;
}
ComPort(String filepath, int baudRate, DeviceType deviceType) {
this.filepath = filepath;
this.baudRate = baudRate;
this.deviceType = deviceType;
}
public String getFilepath() {
return filepath;
}
public int getBaudRate() {
return baudRate;
}
public DeviceType getDeviceType() {
return deviceType;
}
@Override
public String toString() {
return "ComPort{" +
"filepath='" + filepath +
", baudRate=" + baudRate +
", deviceType=" + deviceType.getDescription() +
'}';
}
}

View File

@ -0,0 +1,35 @@
package com.unibuy.smartdevice.devices;
public class DevDigitalDisplay {
private static byte[] bufferTmp = new byte[]{0x10, 0x00, (byte) 0xE8, 0x00, 0x08, 0x10};
public static byte[] getBuffer(int slot, int h, int m, int min) {
byte[] buffer = PortTools.concatByteArrays(PortTools.intToByte8(slot, 1), bufferTmp);
buffer = PortTools.concatByteArrays(buffer, PortTools.charToByte8(String.format("%02d", min), 2));
buffer = PortTools.concatByteArrays(buffer, new byte[] {0x00, 0x2D});
buffer = PortTools.concatByteArrays(buffer, PortTools.charToByte8(String.format("%02d", m), 2));
buffer = PortTools.concatByteArrays(buffer, new byte[] {0x00, 0x2D});
buffer = PortTools.concatByteArrays(buffer, PortTools.charToByte8(String.format("%02d", h), 2));
buffer = PortTools.concatByteArrays(buffer, calculateCRC16(buffer));
return buffer;
}
public static byte[] calculateCRC16(byte[] data) {
int crc = 0xFFFF; // 初始值
for (byte b : data) {
crc ^= (b & 0xFF); // byte 擴展到無符號整數進行異或
for (int i = 0; i < 8; i++) {
if ((crc & 0x0001) != 0) {
crc >>>= 1;
crc ^= 0xA001;
} else {
crc >>>= 1;
}
}
}
// 回傳低位與高位的 byte
return new byte[]{(byte) (crc & 0xFF), (byte) ((crc >> 8) & 0xFF)};
}
}

View File

@ -0,0 +1,493 @@
package com.unibuy.smartdevice.devices;
import android.content.Context;
import android.util.Log;
import androidx.core.view.InputDeviceCompat;
import com.unibuy.smartdevice.R;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsParseException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
public class DevNFCPay {
private Logs logs;
private final byte ACK = 6;
private final byte ETX = 3;
private final byte NAK = 21;
private final byte STX = 2;
private String type = "NCCC";
private String swipeString = "";
private String dataLength = "";
private boolean isScaning = false;
private static Context context;
public DevNFCPay(Context context) {
this.logs = new Logs(this.getClass());
this.context = context.getApplicationContext();
}
// public DevNFCPay() {
// String[] SerialConfig = "/dev/ttymxc2,9600".split(",");
// String pathName = SerialConfig[0];
// int baudrate = Integer.parseInt(SerialConfig[1]);
// if (SerialConfig.length > 2) {
// dataLength = SerialConfig[2];
// type = "TSIB";
// } else {
// type = "NCCC";
// }
// }
public byte[] checkout() { //NCCC信用卡結帳
String date = new SimpleDateFormat("yyMMddHHmmss", Locale.US).format(new Date());
String str = "I 50 " + date + " ";
byte[] data = new byte[403];
data[0] = STX;
System.arraycopy(str.getBytes(), 0, data, 1, str.length());
data[401] = ETX;
for (int i = 1; i < 402; i++) {
data[402] = (byte) (data[402] ^ data[i]);
}
return data;
}
public byte[] reconcile() { //TSIB特約商店結帳
String date = new SimpleDateFormat("yyMMddHHmmss", Locale.US).format(new Date());
String strDefault = dataLength.isEmpty() ? " " : "220001";
String str = dataLength + "I" + strDefault + " 50 " + date + " ";
int l = str.length();
byte[] data = new byte[l + 3];
data[0] = STX;
int l2 = l + 1;
System.arraycopy(str.getBytes(), 0, data, 1, l);
int l3 = l2 + 1;
data[l2] = ETX;
for (int i = 1; i < l3; i++) {
data[l3] = (byte) (data[l3] ^ data[i]);
}
swipeString = new String(data, StandardCharsets.UTF_8).substring(dataLength.length());
return data;
}
public byte[] reset() { //重啟
byte[] data = new byte[403];
data[0] = STX;
System.arraycopy("I 99".getBytes(), 0, data, 1, "I 99".length());
data[401] = ETX;
for (int i = 1; i < 402; i++) {
data[402] = (byte) (data[402] ^ data[i]);
}
return data;
}
/*
170000483***86 00000202206JS2 00900248 cI0702 01300084*69 000201J2000115 i
\u0006
192130096******11 000000248 0000794 1846 200014 M A\/MdC+4PLjtONdrF= M
\u0006
1N 56222231 030047
\u0006
\u0006
9006*7 0000242325064 0015700 020014 3x9iC+4uPL6jtO+eNbUAredrVfpnFL4= T01
\u0003
*/
private HashMap<String, String> decode(String s) {
s.substring(1, 2);
s.substring(2, 8);
s.substring(9, 11);
s.substring(11, 12);
s.substring(12, 14);
s.substring(15, 20);
s.substring(20, 39);
s.substring(39, 43);
s.substring(43, 55);
s.substring(55, 61);
s.substring(61, 67);
s.substring(67, 76);
s.substring(76, 77);
String C15_ResponseCode = s.substring(77, 81);
s.substring(81, 96);
s.substring(96, 104);
s.substring(116, 134);
s.substring(134, 135);
s.substring(175, 177);
s.substring(177, 189);
s.substring(189, 201);
s.substring(201, 213);
s.substring(213, 215);
s.substring(215, 221);
s.substring(223, 224);
s.substring(224, 232);
s.substring(232, 240);
s.substring(240, 252);
s.substring(InputDeviceCompat.SOURCE_KEYBOARD, 307);
s.substring(307, 313);
s.substring(313, 314);
s.substring(314, 315);
s.substring(315, 318);
String responseCode = C15_ResponseCode;
String status = String.valueOf(s.charAt(1));
String category = swipeString.length()>0? swipeString.substring(1): "";
String message = s.substring(1);
logs.info("responseCode:" + responseCode);
logs.info("status:" + status);
logs.info("category:" + category);
logs.info("message:" + message);
HashMap<String, String> responseMap = new HashMap<>();
responseMap.put("code", responseCode);
responseMap.put("status", status);
responseMap.put("category", category);
responseMap.put("message", message);
return responseMap;
}
public HashMap<String, String> read(String rxData) throws LogsParseException {
int stx = rxData.lastIndexOf(String.format("%c", Byte.valueOf(STX)));
int etx = rxData.indexOf(String.format("%c", Byte.valueOf(ETX)));
while (stx > etx) {
stx = rxData.lastIndexOf(String.format("%c", Byte.valueOf(STX)), stx - 1);
}
if (stx >= 0) {
return decode(rxData.substring(dataLength.length() + stx, etx));
} else {
throw new LogsParseException(logs, "Decode parsing failed");
}
}
//check = 3
public byte[] ok() {
return new byte[]{ACK, ACK};
}
public byte[] settlement(int type) {
byte[] data = new byte[401];
Arrays.fill(data, (byte) 32);
data[1] = 73;
System.arraycopy("2200".getBytes(), 0, data, 2, 4);
System.arraycopy("01".getBytes(), 0, data, 6, 2);
switch (type) { //TSIB特約商店結帳
case 1:
System.arraycopy("50".getBytes(), 0, data, 9, 2);
break;
case 251: //一卡通
System.arraycopy("71".getBytes(), 0, data, 9, 2);
System.arraycopy("51".getBytes(), 0, data, 12, 2);
break;
case 252: //悠遊卡
System.arraycopy("71".getBytes(), 0, data, 9, 2);
System.arraycopy("52".getBytes(), 0, data, 12, 2);
break;
}
int l = dataLength.length();
byte[] cmd = new byte[l + 403];
System.arraycopy(dataLength.getBytes(), 0, cmd, 1, l);
System.arraycopy(data, 1, cmd, l + 1, 400);
int l2 = cmd.length - 1;
cmd[0] = STX;
cmd[l2 - 1] = ETX;
for (int i = 1; i < l2; i++) {
cmd[l2] = (byte) (cmd[l2] ^ cmd[i]);
}
swipeString = new String(cmd, StandardCharsets.UTF_8).substring(dataLength.length());
return cmd;
}
public byte[] swipe(int payType, int price) {
isScaning = true;
if (!type.equals("TSIB")) {
return swipeNCCC(payType == 2 ? 'E' : 'N', price);
} else {
return swipeTSIB(payType != 4 ? payType : 1, price);
}
}
public byte[] swipeTSIB(int type, int price) {
Date now = new Date();
byte[] data = new byte[401];
Arrays.fill(data, (byte) 32);
data[1] = 73;
System.arraycopy("2200".getBytes(), 0, data, 2, 4);
System.arraycopy("01".getBytes(), 0, data, 6, 2);
System.arraycopy(String.format(Locale.ROOT, "%012d", Integer.valueOf(price * 100)).getBytes(), 0, data, 43, 12);
System.arraycopy(new SimpleDateFormat("yyMMddHHmmss", Locale.US).format(now).getBytes(), 0, data, 55, 12);
switch (type) {
case 1:
System.arraycopy("01".getBytes(), 0, data, 9, 2);
System.arraycopy(new SimpleDateFormat("yyMMddHHmmssSSSS", Locale.US).format(now).getBytes(), 0, data, 368, 16);
break;
case 251:
System.arraycopy("71".getBytes(), 0, data, 9, 2);
System.arraycopy("51".getBytes(), 0, data, 12, 2);
break;
case 252:
System.arraycopy("71".getBytes(), 0, data, 9, 2);
System.arraycopy("52".getBytes(), 0, data, 12, 2);
break;
}
byte[] cmd = new byte[409];
cmd[0] = STX;
Log.i("swipteISIB", "length:" + dataLength.getBytes());
System.arraycopy(dataLength.getBytes(), 0, cmd, 1, 6);
System.arraycopy(data, 1, cmd, 7, 400);
cmd[407] = ETX;
for (int i = 1; i < 408; i++) {
cmd[408] = (byte) (cmd[408] ^ cmd[i]);
}
swipeString = new String(cmd, StandardCharsets.UTF_8).substring(dataLength.length());
return cmd;
}
private byte[] swipeNCCC(char type2, int price) {
String format = String.format(
Locale.ROOT,
"I 01%c03 %012d%s Nexsys1412 2 ",
Character.valueOf(type2),
Integer.valueOf(price * 100),
new SimpleDateFormat("yyMMddHHmmss", Locale.US).format(new Date()));
swipeString = format;
format.substring(9, 11);
swipeString.charAt(11);
swipeString.substring(12, 14);
swipeString.substring(43, 55);
swipeString.substring(55, 61);
swipeString.substring(61, 67);
swipeString.substring(116, 134);
swipeString.charAt(134);
int l = swipeString.length();
byte[] cmd = new byte[l + 3];
System.arraycopy(swipeString.getBytes(), 0, cmd, 1, l);
int l2 = cmd.length - 1;
cmd[0] = STX;
cmd[401] = ETX;
for (int i = 1; i < l2; i++) {
cmd[l2] = (byte) (cmd[l2] ^ cmd[i]);
}
return cmd;
}
/*
沒有使用
*/
public byte[] echo() {
byte[] data = new byte[409];
Arrays.fill(data, (byte) 32);
data[408] = 0;
System.arraycopy(dataLength.getBytes(), 0, data, 1, dataLength.length());
data[7] = 73;
data[8] = 50;
data[9] = 50;
data[10] = 48;
data[11] = 48;
data[12] = 48;
data[13] = 49;
data[15] = 57;
data[16] = 57;
data[0] = STX;
data[407] = ETX;
for (int i = 1; i < 408; i++) {
data[408] = (byte) (data[408] ^ data[i]);
}
return data;
}
/*
沒有使用
*/
public byte[] abort(char type2, int price) {
String format = String.format(
Locale.ROOT,
"I 30%c03 %012d%s Nexsys1412 2 ",
Character.valueOf(type2),
Integer.valueOf(price * 100),
new SimpleDateFormat("yyMMddHHmmss", Locale.US).format(new Date()));
swipeString = format;
format.substring(9, 11);
swipeString.charAt(11);
swipeString.substring(12, 14);
swipeString.substring(14, 20);
swipeString.substring(43, 55);
swipeString.substring(55, 61);
swipeString.substring(61, 67);
swipeString.substring(116, 134);
swipeString.charAt(134);
int l = swipeString.length();
byte[] cmd = new byte[l + 3];
System.arraycopy(swipeString.getBytes(), 0, cmd, 1, l);
int l2 = cmd.length - 1;
cmd[0] = STX;
cmd[401] = ETX;
for (int i = 1; i < l2; i++) {
cmd[l2] = (byte) (cmd[l2] ^ cmd[i]);
}
return cmd;
}
/*
0000 交易成功
0001 交易失敗
0002 請連絡銀行
0003 交易逾時
0004 操作錯誤
0005 通訊失敗
0006 使用者終止交易
0009 非參加機構卡片
0010 電文錯誤
0011 非聯名卡-客製化參數 075/103 使用
0012 電票金額超過上限
0013 票卡已鎖
0014 無法比對原始電票交易
0015 票卡未開啟自動加值
0016 電票餘額不足
0017 多張票卡讀取失敗
0018 請重新感應卡片
1001 信用卡及電票皆結帳失敗
1002 信用卡結帳成功電票結帳失敗
1003 信用卡結帳失敗電票結帳成功
*/
public static String recordMessage(String code) {
switch (code) {
case "0000":
return context.getString(R.string.successful_transaction);//交易成功
case "0001":
return context.getString(R.string.transaction_failure);//交易失敗
case "0002":
return context.getString(R.string.please_contact_your_bank);//請連絡銀行
case "0003":
return context.getString(R.string.transaction_timeout);//交易逾時
case "0004":
return context.getString(R.string.operational_error);//操作錯誤
case "0005":
return context.getString(R.string.communication_failure);//通訊失敗
case "0006":
return context.getString(R.string.user_terminates_transaction);//使用者終止交易
case "0009":
return context.getString(R.string.non_participating_institution_card);//非參加機構卡片
case "0010":
return context.getString(R.string.message_error);//電文錯誤
case "0011":
return context.getString(R.string.non_co_branded_card_customized_parameters_075_103_use);//非聯名卡-客製化參數 075/103 使用
case "0012":
return context.getString(R.string.amount_of_the_electronic_bill_exceeds_the_upper_limit);//電票金額超過上限
case "0013":
return context.getString(R.string.ticket_locked);//票卡已鎖
case "0014":
return context.getString(R.string.unable_compare_original_electronic_bill_transaction);//無法比對原始電票交易
case "0015":
return context.getString(R.string.ticket_card_has_not_enabled_automatic_recharge);//票卡未開啟自動加值
case "0016":
return context.getString(R.string.insufficient_balance_on_electronic_bill);//電票餘額不足
case "0017":
return context.getString(R.string.multiple_tickets_failed_to_read);//多張票卡讀取失敗
case "0018":
return context.getString(R.string.please_scan_card_again);//請重新感應卡片
case "1001":
return context.getString(R.string.credit_card_electronic_bill_payment_failed);//信用卡及電票皆結帳失敗
case "1002":
return context.getString(R.string.credit_card_payment_successful_electronic_bill_payment_failed);//信用卡結帳成功電票結帳失敗
case "1003":
return context.getString(R.string.credit_card_payment_failed_electronic_bill_payment_succeeded);//信用卡結帳失敗電票結帳成功
}
return context.getString(R.string.abnormal_response_message_error);//回應異常電文錯誤
}
//public static String recordMessage(String code) {
// switch (code) {
// case "0000":
// return context.getString(R.string.successful_transaction);//交易成功
//
// case "0001":
// return "交易失敗";//交易失敗
//
// case "0002":
// return "請連絡銀行";//請連絡銀行
//
// case "0003":
// return "交易逾時";//交易逾時
//
// case "0004":
// return "操作錯誤";//操作錯誤
//
// case "0005":
// return "通訊失敗";//通訊失敗
//
// case "0006":
// return "使用者終止交易";//使用者終止交易
//
// case "0009":
// return "非參加機構卡片";//非參加機構卡片
//
// case "0010":
// return "電文錯誤";//電文錯誤
//
// case "0011":
// return "非聯名卡-客製化參數 075/103 使用";//非聯名卡-客製化參數 075/103 使用
//
// case "0012":
// return "電票金額超過上限";//電票金額超過上限
//
// case "0013":
// return "票卡已鎖";//票卡已鎖
//
// case "0014":
// return "無法比對原始電票交易";//無法比對原始電票交易
//
// case "0015":
// return "票卡未開啟自動加值";//票卡未開啟自動加值
//
// case "0016":
// return "電票餘額不足";//電票餘額不足
//
// case "0017":
// return "多張票卡讀取失敗";//多張票卡讀取失敗
//
// case "0018":
// return "請重新感應卡片";//請重新感應卡片
//
// case "1001":
// return "信用卡及電票皆結帳失敗";//信用卡及電票皆結帳失敗
//
// case "1002":
// return "信用卡結帳成功,電票結帳失敗";//信用卡結帳成功電票結帳失敗
//
// case "1003":
// return "信用卡結帳失敗,電票結帳成功";//信用卡結帳失敗電票結帳成功
//
// }
//
// return "回應異常,電文錯誤";//回應異常電文錯誤
//}
}

View File

@ -0,0 +1,487 @@
package com.unibuy.smartdevice.devices;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsEmptyException;
public class DevXinYuan {
public enum CMD {
CMD_FAFB_STX(new byte[]{(byte) 0xFA, (byte) 0xFB}),
CMD_42_ACK(new byte[]{0x42, 0x00}),
CMD_25_GIVE_CHANGE(new byte[]{0x25, 0x05}), //啟動找零
CMD_27_IN_COME(new byte[]{0x27, 0x06}), //1:紙幣 2:硬幣 8:吞幣
CMD_28_SET_MONEY_TYPE(new byte[]{0x28, 0x04}), //設定接收面值 類型 0:紙幣 1硬幣
CMD_12_SET_PRODUCT_PRICE(new byte[]{0x12, 0x07}),
CMD_12_SET_CONNECT_LIFT(new byte[]{0x12, 0x00}),
CMD_13_SET_PRODUCT_STOCK(new byte[]{0x13, 0x04}),
CMD_14_SET_SLOT_SIZE(new byte[]{0x14, 0x04}),
CMD_15_SET_SLOT_INDEX(new byte[]{0x15, 0x05}),
CMD_01_CHECK_SLOT_STATUS(new byte[]{0x01, 0x03}),
CMD_03_BUY_PRODUCT(new byte[]{0x03, 0x03}), //出貨1 4.3.2
CMD_05_SELECT_UNSELECT_SLOT(new byte[]{0x05, 0x03}),
CMD_06_GET_PRODUCT(new byte[]{0x06, 0x06}), //出貨2 4.3.5
CMD_53_CHECK_MACHINE_STATUS(new byte[]{0x53, 0x01}),
CMD_16_SET_POLL_MS(new byte[]{0x16, 0x02}), //1:100ms~20:2000ms
CMD_31_SYNC_PACK_NO(new byte[]{0x31, 0x01}),
CMD_36_GET_VERSION(new byte[]{0x36, 0x01}),
CMD_37_GIVE_CHANGE_MODE(new byte[]{0x37, 0x02}),
CMD_51_CHECK_VMC_STATUS(new byte[]{0x51, 0x01}),
CMD_70_MENU_SET(new byte[]{0x70, 0x01}),
;
private byte[] bytes;
CMD(byte[] bytes) {
this.bytes = bytes;
}
public byte[] getBytes() {
return bytes;
}
}
public enum VMC {
VMC_FAFB_STX(new byte[]{(byte) 0xFA, (byte) 0xFB}),
VMC_41_POLL(new byte[]{0x41, 0x00}),
VMC_42_ACK(new byte[]{0x42, 0x00}),
VMC_21_GET_MONEY(new byte[]{0x21, 0x06}), //收錢通知:PackON+方式1紙幣2硬幣+金額(4byte)
VMC_23_NOW_GET_TOTAL(new byte[]{0x23, 0x05}), //當前金額
VMC_24_POS_DISPLAY(new byte[]{0x24, 0x19}),
VMC_26_GIVE_CHANGE(new byte[]{0x26, 0x09}),
VMC_27_IN_COME(new byte[]{0x27, 0x06}), //1:紙幣 2:硬幣 8:吞幣
VMC_29_MONEY_SWITCH(new byte[]{0x29, 0x02}),
VMC_11_GIVE_PRODUCT_INFO(new byte[]{0x11, 0x12}),
VMC_12_SET_PRODUCT_PRICE(new byte[]{0x12, 0x07}),
VMC_13_SET_PRODUCT_STOCK(new byte[]{0x13, 0x04}),
VMC_14_SET_SLOT_SIZE(new byte[]{0x14, 0x04}),
VMC_15_SET_SLOT_INDEX(new byte[]{0x15, 0x05}),
VMC_17_SET_STOCK_MAX(new byte[]{0x17, 0x01}),
VMC_02_CHECK_SLOT_STATUS(new byte[]{0x02, 0x04}),
VMC_04_BUY_STATUS(new byte[]{0x04, 0x05}), //出貨3
VMC_05_SELECT_UNSELECT_SLOT(new byte[]{0x05, 0x03}), //選擇或不選擇貨道
VMC_54_CHECK_MACHINE_STATUS(new byte[]{0x54, 0x01}),
VMC_31_SYNC_PACK_NO(new byte[]{0x31, 0x01}),
VMC_32_GET_VERSION(new byte[]{0x32, 0x01}),
VMC_33_PASS_GIVE_CHANGE(new byte[]{0x33, 0x00}),
VMC_38_GIVE_CHANGE_MODE(new byte[]{0x38, 0x02}),
VMC_52_CHECK_VMC_STATUS(new byte[]{0x52, 0x01}),
VMC_63_CLICK_RED_BUTTON(new byte[]{0x63, 0x01}),
VMC_66_PO_MICROWAVE_STATUS(new byte[]{0x66, 0x01}),
VMC_67_PO_MACHINE_STATUS(new byte[]{0x67, 0x01}),
VMC_71_MENU_GET(new byte[]{0x71, 0x01}),
;
private byte[] bytes;
VMC(byte[] bytes) {
this.bytes = bytes;
}
public byte[] getBytes() {
return bytes;
}
}
public enum GIVE_MONEY_26 {
GET_MONEY_01_BILL(new byte[]{0x01}),
GET_MONEY_02_COIN(new byte[]{0x02}),
GET_MONEY_08_GET_COIN(new byte[]{0x08}),
;
private byte[] bytes;
GIVE_MONEY_26(byte[] bytes) {
this.bytes = bytes;
}
public byte[] getBytes() {
return bytes;
}
}
public enum SLOT_STATUS_02 {
SLOT_STATUS_01_OK(new byte[]{0x01}),
SLOT_STATUS_02_PDT_EMPTY(new byte[]{0x02}),
SLOT_STATUS_03_SLOT_EMPTY(new byte[]{0x03}),
SLOT_STATUS_04_SLOT_TMP_USE(new byte[]{0x04}),
SLOT_STATUS_05(new byte[]{0x05}),
SLOT_STATUS_06_NOT_CLOSE(new byte[]{0x06}),
SLOT_STATUS_07_ERROR(new byte[]{0x07}),
SLOT_STATUS_08_ERROR(new byte[]{0x08}),
SLOT_STATUS_09_ERROR(new byte[]{0x09}),
SLOT_STATUS_0A_ERROR(new byte[]{0x0A}),
SLOT_STATUS_10_ERROR(new byte[]{0x10}),
SLOT_STATUS_11_ERROR(new byte[]{0x11}),
SLOT_STATUS_12_BOX_EMPTY(new byte[]{0x12}),
SLOT_STATUS_13_BOX_HOT(new byte[]{0x13}),
SLOT_STATUS_14_ERROR(new byte[]{0x14}),
SLOT_STATUS_15_PLIS_BOX(new byte[]{0x15}),
SLOT_STATUS_16_ERROR(new byte[]{0x16}),
SLOT_STATUS_17_ERROR(new byte[]{0x17}),
SLOT_STATUS_18_ERROR(new byte[]{0x18}),
SLOT_STATUS_19_ERROR(new byte[]{0x19}),
SLOT_STATUS_20_ERROR(new byte[]{0x20}),
SLOT_STATUS_21_ERROR(new byte[]{0x21}),
SLOT_STATUS_22_ERROR(new byte[]{0x22}),
SLOT_STATUS_23_ERROR(new byte[]{0x23}),
SLOT_STATUS_24(new byte[]{0x24}),
SLOT_STATUS_25(new byte[]{0x25}),
SLOT_STATUS_26(new byte[]{0x26}),
SLOT_STATUS_27(new byte[]{0x27}),
SLOT_STATUS_28(new byte[]{0x28}),
SLOT_STATUS_29(new byte[]{0x29}),
SLOT_STATUS_30(new byte[]{0x30}),
SLOT_STATUS_31(new byte[]{0x31}),
SLOT_STATUS_32(new byte[]{0x32}),
SLOT_STATUS_FF(new byte[]{(byte) 0xFF});
private byte[] bytes;
SLOT_STATUS_02(byte[] bytes) {
this.bytes = bytes;
}
public byte[] getBytes() {
return bytes;
}
}
public enum BUY_STATUS_04 {
BUY_STATUS_01_NOW(new byte[]{0x01}),
BUY_STATUS_02_OK(new byte[]{0x02}),
BUY_STATUS_03_K_PDT(new byte[]{0x03}),
BUY_STATUS_04_NOT_STOP(new byte[]{0x04}),
BUY_STATUS_05(new byte[]{0x05}),
BUY_STATUS_06_NOT_FOUND(new byte[]{0x06}),
BUY_STATUS_07_ERROR(new byte[]{0x07}),
BUY_STATUS_08_ERROR(new byte[]{0x08}),
BUY_STATUS_09_ERROR(new byte[]{0x09}),
BUY_STATUS_0A_ERROR(new byte[]{0x0A}),
BUY_STATUS_10_PLATFORM_UP(new byte[]{0x10}),
BUY_STATUS_11_PLATFORM_DOWN(new byte[]{0x11}),
BUY_STATUS_12_PLATFORM_UP_ERROR(new byte[]{0x12}),
BUY_STATUS_13_PLATFORM_DOWN_ERROR(new byte[]{0x13}),
BUY_STATUS_14_GET_DOOR_CLOSE(new byte[]{0x14}),
BUY_STATUS_15_GET_DOOR_ERROR(new byte[]{0x15}),
BUY_STATUS_16_SEND_DOOR_OPEN(new byte[]{0x16}),
BUY_STATUS_17_SEND_DOOR_OPEN_ERROR(new byte[]{0x17}),
BUY_STATUS_18_BOX_SEND_NOW(new byte[]{0x18}),
BUY_STATUS_19_SEND_DOOR_CLOSE(new byte[]{0x19}),
BUY_STATUS_20_SEND_DOOR_CLOSE_ERROR(new byte[]{0x20}),
BUY_STATUS_21_BOX_EMPTY(new byte[]{0x21}),
BUY_STATUS_22_BOX_HOT(new byte[]{0x22}),
BUY_STATUS_23_BOX_HOT_TIME(new byte[]{0x23}),
BUY_STATUS_24_PLIS_BOX(new byte[]{0x24}),
BUY_STATUS_25_ERROR(new byte[]{0x25}),
BUY_STATUS_26_MICROWAVE_DOOR_OPEN(new byte[]{0x26}),
BUY_STATUS_27_MICROWAVE_DOOR_OPEN_ERROR(new byte[]{0x27}),
BUY_STATUS_28_ERROR(new byte[]{0x28}),
BUY_STATUS_29_ERROR(new byte[]{0x29}),
BUY_STATUS_30_ERROR(new byte[]{0x30}),
BUY_STATUS_31_ERROR(new byte[]{0x31}),
BUY_STATUS_32_ERROR(new byte[]{0x32}),
BUY_STATUS_FF_SHAPING_STOP(new byte[]{(byte) 0xFF});
private byte[] bytes;
BUY_STATUS_04(byte[] bytes) {
this.bytes = bytes;
}
public byte[] getBytes() {
return bytes;
}
}
public enum MACHINE_STATUS_54 {
MACHINE_STATUS_00_OK(new byte[(byte)0x00]),
MACHINE_STATUS_01_UPDOWN_BOX_HF(new byte[0x01]),
MACHINE_STATUS_02_GET_DOOR_NOT_CLOSE(new byte[0x02]),
MACHINE_STATUS_03_UPDOWN_ERROR(new byte[0x03]),
MACHINE_STATUS_04_UPDOWN_ERROR2(new byte[0x04]);
private byte[] bytes;
MACHINE_STATUS_54(byte[] bytes) {
this.bytes = bytes;
}
public byte[] getBytes() {
return bytes;
}
}
private Logs logs;
private boolean isRun;
private int retryCount = 0;
private byte packNo = 0x00;
public boolean isRun() {
return isRun;
}
public void setRun(boolean run) {
isRun = run;
}
public int getRetryCount() {
return retryCount;
}
public int addRetryCount() {
return this.retryCount+=1;
}
public int initRetryCount() {
return this.retryCount = 0;
}
public boolean isRetryMax() {
logs.info("retryCount:"+this.retryCount);
boolean isRetryMax = this.retryCount >= 5;
return isRetryMax;
}
public boolean isRetryMin() {
boolean isRetryMin = this.retryCount >= 1;
return isRetryMin;
}
public DevXinYuan() {
logs = new Logs(this.getClass());
this.packNo = 0x00;
}
public byte getXOR(byte[] buffer) {
byte checksum = 0x00;
for (byte value : buffer) {
checksum ^= value; // 按位異或
}
return checksum;
}
public byte[] send(CMD cmd, byte[] dataBytes) {
return send(cmd, dataBytes, true);
}
public byte[] send(CMD cmd, byte[] dataBytes, boolean isShow) {
byte[] proBytes = CMD.CMD_FAFB_STX.getBytes();
proBytes = PortTools.concatByteArrays(proBytes, cmd.getBytes());
proBytes = PortTools.concatByteArrays(proBytes, dataBytes);
byte[] XORByte = new byte[] {getXOR(proBytes)};
proBytes = PortTools.concatByteArrays(proBytes, XORByte);
if (isShow) {
logs.info("XinYuan ipcCmd:" + cmd.name() + " " + PortTools.showHex(proBytes));
}
return proBytes;
}
public byte[] syncPackNo(byte packNo) {
this.packNo = packNo;
return send(CMD.CMD_31_SYNC_PACK_NO, new byte[] {
packNo
});
}
public void setPackNo(byte packNo) {
this.packNo = packNo;
}
public byte getPackNo(byte addIndex) {
this.packNo += addIndex;
// logs.info("Send packNo:" + PortTools.showHex(packNo));
return this.packNo;
}
public byte[] sendACK() {
return send(CMD.CMD_42_ACK, new byte[0]);
}
public byte[] sendACKByIsShow(boolean isShow) {
return send(CMD.CMD_42_ACK, new byte[0], isShow);
}
//1:紙幣 2:硬幣 8:紙幣和硬幣
//0:0000 1:0001 2:0010 4:0100 8:1000
public byte[] inComeByIPC(byte mode, int money) {
byte[] bytes = PortTools.intToByte8(money, 4);
return send(CMD.CMD_27_IN_COME, new byte[]{
getPackNo((byte)0x01), mode, bytes[0], bytes[1], bytes[2], bytes[3]
});
}
//設定現金機可吃鈔或吃幣
public byte[] setMoneyType(byte mode, byte set1, byte set2) {
return send(CMD.CMD_28_SET_MONEY_TYPE, new byte[]{
getPackNo((byte)0x01), mode, set1, set2
});
}
//1:紙幣 2:硬幣
//0:不接收 65535:全接收
public byte[] setMoneyType(byte mode, int parValue) {
byte[] bytes = PortTools.intToByte8(parValue, 2);
return send(CMD.CMD_28_SET_MONEY_TYPE, new byte[]{
getPackNo((byte)0x01), mode, bytes[0], bytes[1]
});
}
public byte[] setPollMs(byte ms) {
return send(CMD.CMD_16_SET_POLL_MS, new byte[] {
getPackNo((byte)0x01), ms
});
}
public byte[] buyProduct(int slot) {
byte[] buffer = PortTools.intToByte8(slot, 2);
return send(CMD.CMD_03_BUY_PRODUCT, new byte[]{
getPackNo((byte)0x01), buffer[0], buffer[1]
});
}
public byte[] getProduct(int slot) {
byte[] buffer = PortTools.intToByte8(slot, 2);
return send(CMD.CMD_06_GET_PRODUCT, new byte[]{
getPackNo((byte)0x01), 0x01, 0x01, buffer[0], buffer[1], 0x00
});
}
public byte[] checkSlot(int slot) {
byte[] buffer = PortTools.intToByte8(slot, 2);
return send(CMD.CMD_01_CHECK_SLOT_STATUS, new byte[] {
getPackNo((byte)0x01), buffer[0], buffer[1]
});
}
public byte[] checkSlotPre(int slot,int slotcount) {
byte[] buffer = PortTools.intToByte8(slot, 2);
byte[] buffer2 = PortTools.intToByte8(slotcount, 1);
return send(CMD.CMD_13_SET_PRODUCT_STOCK, new byte[] {
getPackNo((byte)0x01), buffer[0], buffer[1], buffer2[0]});
}
public byte[] giveChangeMode(boolean isIPC) {
return send(CMD.CMD_37_GIVE_CHANGE_MODE, new byte[] {
getPackNo((byte)0x01), isIPC ? (byte)0x01: (byte)0x02
});
}
//GIVE_CHANGE
public byte[] giveChange(int price) {
byte[] buffer = PortTools.intToByte8(price*100, 4);
return send(CMD.CMD_25_GIVE_CHANGE, new byte[] {
getPackNo((byte)0x01), buffer[0], buffer[1], buffer[2], buffer[3]
});
}
public CMD readCMD(byte[] buffer) throws LogsEmptyException {
logs.info(PortTools.showHex(buffer));
for (CMD cmd : CMD.values()) {
if (cmd.getBytes().length >= 2 && buffer.length >= 2) {
if (cmd.getBytes()[0] == buffer[0]) {
if (cmd.equals(CMD.CMD_FAFB_STX)) {
if (cmd.getBytes()[1] == buffer[1]) {
logs.info("CMD:" + cmd.name() + " " + PortTools.showHex(cmd.getBytes()) + " buffer:" + PortTools.showHex(new byte[]{buffer[0], buffer[1]}));
return cmd;
}
} else {
logs.info("CMD:" + cmd.name() + " " + PortTools.showHex(cmd.getBytes()) + " buffer:" + PortTools.showHex(new byte[]{buffer[0], buffer[1]}));
return cmd;
}
}
}
}
throw new LogsEmptyException(logs, "cmd command not found:"+PortTools.showHex(buffer));
}
public VMC readVMC(byte[] buffer) throws LogsEmptyException {
logs.info(PortTools.showHex(buffer));
for (VMC vmc : VMC.values()) {
if (vmc.getBytes().length >= 2 && buffer.length >= 2) {
if (vmc.getBytes()[0] == buffer[0]) {
if (vmc.equals(VMC.VMC_FAFB_STX)) {
if (vmc.getBytes()[1] == buffer[1]) {
logs.info("VMC:" + vmc.name() + " " + PortTools.showHex(vmc.getBytes()) + " buffer:" + PortTools.showHex(new byte[]{buffer[0], buffer[1]}));
return vmc;
}
} else {
logs.info("VMC:" + vmc.name() + " " + PortTools.showHex(vmc.getBytes()) + " buffer:" + PortTools.showHex(new byte[]{buffer[0], buffer[1]}));
return vmc;
}
}
}
}
throw new LogsEmptyException(logs, "vmc command not found:"+PortTools.showHex(buffer));
}
public byte readPackNo(byte[] buffer) {
byte packNo = buffer[0];
logs.info("Read packNo:" + PortTools.showHex(packNo));
return packNo;
}
public BUY_STATUS_04 readBuyStatus(byte[] buffer) throws LogsEmptyException {
for (BUY_STATUS_04 buyStatus : BUY_STATUS_04.values()) {
if (buyStatus.getBytes().length == 1 && buffer.length > 0) {
if (buyStatus.getBytes()[0] == buffer[1]) {
logs.info(BUY_STATUS_04.class.getSimpleName()+":" + buyStatus.name() + " " + PortTools.showHex(buyStatus.getBytes()) + " buffer:" + PortTools.showHex(new byte[]{buffer[0], buffer[1]}));
return buyStatus;
}
}
}
throw new LogsEmptyException(logs, "buy status command not found");
}
public SLOT_STATUS_02 readSlotStatus(byte[] buffer) throws LogsEmptyException {
for (SLOT_STATUS_02 slotStatus : SLOT_STATUS_02.values()) {
if (slotStatus.getBytes().length == 1 && buffer.length > 0) {
if (slotStatus.getBytes()[0] == buffer[1]) {
logs.info(SLOT_STATUS_02.class.getSimpleName()+":" + slotStatus.name() + " " + PortTools.showHex(slotStatus.getBytes()) + " buffer:" + PortTools.showHex(new byte[]{buffer[0], buffer[1]}));
return slotStatus;
}
}
}
throw new LogsEmptyException(logs, "buy status command not found");
}
//GIVE_MONEY
public GIVE_MONEY_26 readGiveMoney(byte[] buffer) throws LogsEmptyException {
for (GIVE_MONEY_26 giveMoney : GIVE_MONEY_26.values()) {
if (giveMoney.getBytes().length == 1 && buffer.length > 0) {
if (giveMoney.getBytes()[0] == buffer[1]) {
logs.info(GIVE_MONEY_26.class.getSimpleName()+":" + giveMoney.name() + " " + PortTools.showHex(giveMoney.getBytes()) + " buffer:" + PortTools.showHex(new byte[]{buffer[0], buffer[1]}));
return giveMoney;
}
}
}
throw new LogsEmptyException(logs, "buy status command not found");
}
public int readMoney(byte[] buffer, int strPos, int endPos) {
byte[] result = new byte[endPos - strPos +1];
for (int i = strPos; i <= endPos; i++) {
result[i-strPos] = buffer[i];
}
return PortTools.byte8ToInt(result);
}
public byte[] readData(byte[] buffer) throws LogsEmptyException {
int length = buffer[1];
byte[] proBytes = VMC.VMC_FAFB_STX.getBytes();
byte[] cmdLenData = PortTools.catByteArrays(buffer, 0, buffer.length-1);
byte XORByte = buffer[buffer.length -1];
proBytes = PortTools.concatByteArrays(proBytes, cmdLenData);
byte XORByte2 = getXOR(proBytes);
logs.info("Length:"+length+" XOR1:" + PortTools.showHex(new byte[] {XORByte}) + " XOR2:" + PortTools.showHex(new byte[] {XORByte2}));
if (buffer.length > (2+length)) {
byte[] dataBytes = PortTools.catByteArrays(buffer, 2, length);
logs.info("data:"+PortTools.showHex(dataBytes));
return dataBytes;
} else {
throw new LogsEmptyException(logs, "data array length insufficient");
}
}
}

View File

@ -0,0 +1,26 @@
package com.unibuy.smartdevice.devices;
public enum DeviceType {
UNKNOWN("Unknown"),
PRINTER("Printer"),
SCANNER("Scanner"),
NFC_SCANNER("NFCScanner"),
QRCODE_SCANNER("QRCodeScanner"),
SENSOR("Sensor"),
XINYUAN("XinYuan"),
IDENTIFICATION("Identification"),
DIGITAL_DISPLAY("DigitalDisplay"),
ELECTRIC("electric"),
;
private final String description;
DeviceType(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}

View File

@ -0,0 +1,170 @@
package com.unibuy.smartdevice.devices;
import java.util.List;
public class PortTools {
public static byte[] catByteArrays(byte[] array1, int index) {
return catByteArrays(array1, index, array1.length-index);
}
public static byte[] catByteArrays(byte[] array1, int index, int count) {
byte[] result = new byte[count];
System.arraycopy(array1, index, result, 0, count);
return result;
}
public static byte[] concatByteArrays(byte byte1, byte byte2) {
return concatByteArrays(new byte[]{byte1}, new byte[]{byte2});
}
public static byte[] concatByteArrays(byte[] array1, byte[] array2) {
byte[] result = new byte[array1.length + array2.length];
// 複製第一個陣列
System.arraycopy(array1, 0, result, 0, array1.length);
// 複製第二個陣列
System.arraycopy(array2, 0, result, array1.length, array2.length);
return result;
}
public static byte[] subtractByteArrays(byte[] array1, int count) {
byte[] result = new byte[array1.length-count];
// 複製第一個陣列
System.arraycopy(array1, 0, result, 0, array1.length-1);
return result;
}
public static byte[] intToByte8(int decimal, int count) {
byte[] bytes = new byte[count];
for(int i=0; i<count; i++) {
bytes[count-1-i] = (byte) (decimal >> 8*i);
}
return bytes;
}
public static byte[] charToByte8(String string, int count) {
byte[] buffer = new byte[0];
for (int index = string.length()-1; index >= 0; index --) {
char character = string.charAt(index);
int unicode = Character.codePointAt(new char[]{character}, 0);
buffer = PortTools.concatByteArrays(buffer, PortTools.intToByte8(unicode, count));
}
return buffer;
}
public static int byte8ToInt(byte byte0, byte byte1, byte byte2, byte byte3) {
byte[] bytes = new byte[]{byte0, byte1, byte2, byte3};
return byte8ToInt(bytes);
}
public static int byte8ToInt(byte byte0, byte byte1, byte byte2) {
byte[] bytes = new byte[]{byte0, byte1, byte2};
return byte8ToInt(bytes);
}
public static int byte8ToInt(byte byte0, byte byte1) {
byte[] bytes = new byte[]{byte0, byte1};
return byte8ToInt(bytes);
}
public static int byte8ToInt(byte byte0) {
byte[] bytes = new byte[]{byte0};
return byte8ToInt(bytes);
}
public static int byte8ToInt(byte[] bytes) {
int result = 0;
for(int i=0; i<bytes.length; i++) {
result = (result << 8) | (bytes[i] & 0xFF);
}
return result;
}
public static byte tenToHexToByte(int decimal) {
String hexString = Integer.toHexString(decimal).toUpperCase();
return (byte) Integer.parseInt(hexString, 16);
}
public static String showBinary(byte[] data) {
StringBuilder binaryStringBuilder = new StringBuilder();
for (int i = 0; i < data.length; i++) {
// byte 轉成二進位字串並補 0
String binaryString = String.format("%8s", Integer.toBinaryString(data[i] & 0xFF))
.replace(' ', '0');
binaryStringBuilder.append(binaryString);
// 在每個二進位字串後加一個空格除了最後一個
if (i < data.length - 1) {
binaryStringBuilder.append(" ");
}
}
return binaryStringBuilder.toString();
}
public static String showHex(byte data) {
return showHex(new byte[]{data});
}
public static String showHex(byte[] data) {
StringBuilder hexStringBuilder = new StringBuilder();
for (int i = 0; i < data.length; i++) {
// byte 轉成十六進位字串
String hexString = String.format("%02X", data[i] & 0xFF);
hexStringBuilder.append(hexString);
// 在每個十六進位字串後加一個空格除了最後一個
if (i < data.length - 1) {
hexStringBuilder.append(" ");
}
}
return hexStringBuilder.toString();
}
private static int matchIndex = 0;
public static int getMatchIndex() {
return matchIndex;
}
public static boolean match(byte oneByte, byte[] matchBytes) {
if (matchIndex > matchBytes.length-1) matchIndex = 0;
if (oneByte == matchBytes[matchIndex]) {
if (matchIndex == matchBytes.length-1) {
return true;
} else {
matchIndex ++;
return false;
}
} else {
return false;
}
}
public static byte[] calculateCRC(byte[] data, int byteCount) {
int crc = (byte) 0xFFFF;
for (int pos = 0; pos < data.length; pos++) {
crc ^= data[pos] & 0xFF;
for (int i = 8; i != 0; i--) {
if ((crc & 0x0001) != 0) {
crc >>= 1;
crc ^= 0xA001; // Modbus CRC Polynomial
} else {
crc >>= 1;
}
}
}
return intToByte8(crc, byteCount);
}
}

View File

@ -0,0 +1,360 @@
package com.unibuy.smartdevice.devices;
import android.content.Context;
import android.serialport.SerialPort;
import android.util.Log;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsSecurityException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
public class Rs232Dev {
private Logs logs;
private boolean showLogs = false;
private static List<String> rs232DeviceList;
private SerialPort serialPort;
private InputStream inputStream;
private boolean isRead = false;
public void setRead(boolean read) {
isRead = read;
}
public boolean isRead() {
return isRead;
}
public static String searchSuPath() throws LogsSecurityException {
File fileSu = new File("/system/bin/su_root");
if (!fileSu.exists()) {
fileSu = new File("/system/bin/su");
if (!fileSu.exists()) {
fileSu = new File("/system/xbin/su");
}
}
if (fileSu.exists()) {
return fileSu.getAbsolutePath();
} else {
throw new LogsSecurityException(new Logs(Rs232Dev.class), "su file not found");
}
}
private static String suPath;
public static void setSuPath(Context context) {
try {
suPath = searchSuPath();
SerialPort.setSuPath(suPath);
} catch (LogsSecurityException e) {
throw new RuntimeException(e);
}
}
public Rs232Dev() {
this.logs = new Logs(this.getClass());
initDeviceList();
}
public Rs232Dev(ComPort comPort) throws LogsUnsupportedOperationException, LogsIOException {
this();
connectPort(comPort);
}
private void initDeviceList() {
if (rs232DeviceList == null) rs232DeviceList = new ArrayList<>();
if (rs232DeviceList.isEmpty()) {
for (ComPort comPort: ComPort.values()) {
if (chmod666File(comPort.getFilepath())) {
rs232DeviceList.add(comPort.getFilepath());
}
}
}
}
public void clearBuffer() throws LogsIOException {
if (inputStream == null) {
logs.info("InputStream 為 null無法清除緩衝區");
return;
}
try {
while (inputStream.available() > 0) {
inputStream.read();
}
} catch (IOException e) {
throw new LogsIOException(logs, "清除RS232緩衝區失敗", e);
}
}
private boolean chmod666File(String comPortPath) {
if (showLogs) this.logs.info("chmod666File getDevice:" + comPortPath);
File fileComPort = new File(comPortPath);
if (!fileComPort.exists()) {
if (showLogs) this.logs.info(fileComPort.getAbsolutePath() + " not exists:" + fileComPort.exists());
return false;
}
if (showLogs) this.logs.info(fileComPort.getAbsolutePath() + " exists:true canRead:" + fileComPort.canRead() + " canWrite:" + fileComPort.canWrite());
if (fileComPort.canRead() && fileComPort.canWrite()) {
return true;
}
try {
if (showLogs) this.logs.info("suPath:" + suPath);
Process su = Runtime.getRuntime().exec(suPath);
String cmd = "chmod 666 " + fileComPort.getAbsolutePath() + "\nexit\n";
su.getOutputStream().write(cmd.getBytes());
su.getOutputStream().flush();
// 使用執行緒處理標準輸出和錯誤輸出
Thread stdoutThread = new Thread(() -> readStream(su.getInputStream(), showLogs, "OUTPUT"));
Thread stderrThread = new Thread(() -> readStream(su.getErrorStream(), showLogs, "ERROR"));
stdoutThread.start();
stderrThread.start();
// 等待子程序完成
int exitCode = su.waitFor();
// 等待輸出執行緒結束
stdoutThread.join();
stderrThread.join(); // 確保執行緒執行完畢
if (su.waitFor() != 0) {
return false;
}
if (showLogs) this.logs.info(fileComPort.getAbsolutePath() + " set canRead:" + fileComPort.canRead() + " canWrite:" + fileComPort.canWrite());
if (fileComPort.canRead() && fileComPort.canWrite()) {
return true;
} else {
return false;
}
} catch (IOException | InterruptedException e) {
this.logs.info(fileComPort.getAbsolutePath() + " error");
return false;
}
}
private void readStream(InputStream inputStream, boolean showLogs, String streamType) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = reader.readLine()) != null) {
if (showLogs) {
logs.info(streamType + ": " + line);
}
}
} catch (IOException e) {
logs.warning(e);
}
}
public void connectPort(ComPort comPort) throws LogsUnsupportedOperationException, LogsIOException {
// 校验位0:无校验位(NONE默认)1:奇校验位(ODD);2:偶校验位(EVEN)
// Check bit; 0: no check bit (NONE, default); 1: odd check bit (ODD); 2: even check bit (EVEN)
// .parity(2)
// 数据位,默认8可选值为5~8
// Data bit, default 8; optional value is 5~8
// .dataBits(7)
// 停止位默认11:1位停止位2:2位停止位
// Stop bit, default 1; 1:1 stop bit; 2: 2 stop bit
// .stopBits(2)
try {
if (rs232DeviceList.contains(comPort.getFilepath())) {
// closePort();
this.serialPort = SerialPort
.newBuilder(comPort.getFilepath(), comPort.getBaudRate())
.build();
if (showLogs) Log.i("connect", "file:" + comPort.getFilepath() + " baudrate:" + comPort.getBaudRate());
} else {
throw new LogsIOException(logs, "Serialport not found:" + comPort.getFilepath());
}
} catch (IOException e) {
throw new LogsIOException(logs, e.getLocalizedMessage());
}
}
public byte[] readToMatch(byte stx1, byte stx2, int moveLimit) throws LogsIOException {
return readToMatch(new byte[]{stx1, stx2}, moveLimit);
}
public byte[] readToMatch(byte stx1, int moveLimit) throws LogsIOException {
return readToMatch(new byte[]{stx1}, moveLimit);
}
public byte[] readToMatch(byte[] stx, int moveLimit) throws LogsIOException {
byte[] buffer = new byte[0];
try {
InputStream inputStream = this.serialPort.getInputStream();
int moveCount = 0;
while (moveCount <= moveLimit || moveLimit == 0) {
byte[] tmp = new byte[1];
if (inputStream.read(tmp) >= 1) {
if (PortTools.match(tmp[0], stx)) {
buffer = PortTools.concatByteArrays(buffer, tmp);
return buffer;
} else {
buffer = PortTools.concatByteArrays(buffer, tmp);
}
}
moveCount++;
}
return buffer;
} catch (IOException e) {
throw new LogsIOException(logs, e.getLocalizedMessage());
}
}
public byte[] readListen(int readMax, long delayMillis) throws LogsIOException {
InputStream inputStream = this.serialPort.getInputStream();
byte[] buffer = new byte[0];
int readCount = 0;
while (true) {
try {
int size = inputStream.available();
// logs.info("size:" + size);
if (size > 0) {
byte[] tmp = new byte[size];
inputStream.read(tmp);
buffer = PortTools.concatByteArrays(buffer, tmp);
} else {
Thread.sleep(delayMillis);
}
} catch (IOException e) {
throw new LogsIOException(logs, "readListen:" + e.getMessage());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
readCount++;
if (readCount >= readMax) break;
}
if (showLogs) logs.debug("read buffer:"+PortTools.showHex(buffer));
return buffer;
}
public int read(byte[] buffer) throws LogsIOException {
try {
InputStream inputStream = this.serialPort.getInputStream();
int size = inputStream.read(buffer);
if (showLogs) logs.debug("read buffer:"+PortTools.showHex(buffer));
return size;
} catch (IOException e) {
throw new LogsIOException(logs, "read:" + e.getMessage());
}
}
public void send(byte[] buffer) throws LogsIOException {
try {
OutputStream outputStream = this.serialPort.getOutputStream();
outputStream.write(buffer);
outputStream.flush();
if (showLogs) logs.debug("send buffer:"+PortTools.showHex(buffer));
} catch (IOException e) {
throw new LogsIOException(logs, "send:" + e.getMessage());
}
}
public int transmission(byte[] sendBuffer, byte[] readBuffer) throws LogsIOException {
try {
OutputStream outputStream = this.serialPort.getOutputStream();
InputStream inputStream = this.serialPort.getInputStream();
outputStream.write(sendBuffer);
outputStream.flush();
if (showLogs) logs.debug("send buffer:"+PortTools.showHex(sendBuffer));
int size = inputStream.read(readBuffer);
if (showLogs) logs.debug("read buffer:"+PortTools.showHex(readBuffer));
return size;
} catch (IOException e) {
throw new LogsIOException(logs, e.getLocalizedMessage());
}
}
public void closePort() throws LogsIOException {
if (this.serialPort != null) {
// OutputStream outputStream = this.serialPort.getOutputStream();
// if (outputStream != null) {
// outputStream.close();
// outputStream = null;
// }
//
// InputStream inputStream = this.serialPort.getInputStream();
// if (inputStream != null) {
// inputStream.close();
// inputStream = null;
// }
SerialPort serialPort = this.serialPort;
if (serialPort != null) {
serialPort.close();
}
}
}
// 新增真正非阻塞讀取方法
public byte[] readNonBlocking() throws LogsIOException {
try {
InputStream inputStream = serialPort.getInputStream();
int available = inputStream.available();
if (available > 0) {
byte[] buffer = new byte[available];
int size = inputStream.read(buffer);
if (size > 0) {
if (showLogs) logs.debug("readNonBlocking buffer: " + PortTools.showHex(buffer));
return buffer;
}
}
return new byte[0]; // 沒資料就回傳空陣列
} catch (IOException e) {
throw new LogsIOException(logs, "readNonBlocking: " + e.getMessage());
}
}
public boolean isPortOpen() {
return this.serialPort != null; // 或根據實作狀況判斷連線狀態
}
public static void getDeviceInfo() {
System.out.println("----- 偵測Su檔 -----");
try {
System.out.println(searchSuPath());
} catch (LogsSecurityException e) {
System.out.println("找不到Su檔案");
}
System.out.println("----- 遍巡tty檔 -----");
File devDir = new File("/dev");
if (devDir.exists() && devDir.isDirectory()) {
String[] files = devDir.list();
if (files != null) {
for (String file : files) {
if (file.contains("tty")) {
File ttyFile = new File("/dev/"+file);
System.out.println(ttyFile.getAbsolutePath() + " exists:true canRead:" + ttyFile.canRead() + " canWrite:" + ttyFile.canWrite());
}
}
} else {
System.out.println("無法列出 /dev 目錄內容。");
}
} else {
System.out.println("/dev 目錄不存在或無法訪問。");
}
}
}

View File

@ -0,0 +1,109 @@
package com.unibuy.smartdevice.devices;
import java.util.ArrayList;
import java.util.List;
/*
9600, 8, 1, NONE/EVEN
Checking device: /dev/bus/usb/004/007 開發板
Vendor ID: 8746
Product ID: 1
Checking device: /dev/bus/usb/001/002 螢幕線
Vendor ID: 7694
Product ID: 36865
Checking device: /dev/bus/usb/004/011 掃碼頭
Vendor ID: 4619
Product ID: 33286
*/
public enum SerialPort {
IDENTIFICATION(0, 65535, 9600, 8, 1, "NONE", DeviceType.IDENTIFICATION),
UNKNOWN1(0, 65535, 9600, 8, 1, "NONE", DeviceType.UNKNOWN),
UNKNOWN2(1, 65535, 9600, 8, 1, "NONE", DeviceType.UNKNOWN),
UNKNOWN3(2, 65535, 9600, 8, 1, "NONE", DeviceType.UNKNOWN),
STATIC5(3034, 33106, 9600, 8, 1, "NONE", DeviceType.UNKNOWN),
STATIC1(6791, 29987, 9600, 8, 1, "NONE", DeviceType.UNKNOWN),
STATIC2(3034, 61817, 9600, 8, 1, "NONE", DeviceType.UNKNOWN),
STATIC3(8746, 1, 9600, 8, 1, "NONE", DeviceType.UNKNOWN),
STATIC4(7694, 36865, 9600, 8, 1, "NONE", DeviceType.UNKNOWN),
QRCODE_SCANNER1(4619, 33286, 9600, 8, 1, "NONE", DeviceType.QRCODE_SCANNER),
QRCODE_SCANNER2(5418, 34831, 9600, 8, 1, "NONE", DeviceType.QRCODE_SCANNER),
QRCODE_SCANNER3(1317, 42151, 9600, 8, 1, "NONE", DeviceType.QRCODE_SCANNER),
;
private final int vendorID;
private final int productID;
private final int baudRate;
private final int dataBits;
private final int stopBits;
private final String parity;
private final DeviceType deviceType;
// 靜態篩選方法
public static List<SerialPort> getPortsByDeviceType(DeviceType type) {
List<SerialPort> result = new ArrayList<>();
for (SerialPort port : SerialPort.values()) {
if (port.getDeviceType() == type) {
result.add(port);
}
}
return result;
}
public static SerialPort getPortsByVendorInfo(int vendorID, int productID) {
for (SerialPort serialPort : SerialPort.values()) {
if (serialPort.getVendorID() == vendorID && serialPort.getProductID() == productID) {
return serialPort;
}
}
return SerialPort.IDENTIFICATION;
}
SerialPort(int vendorID, int productID, int baudRate, int dataBits, int stopBits, String parity, DeviceType deviceType) {
this.vendorID = vendorID;
this.productID = productID;
this.baudRate = baudRate;
this.dataBits = dataBits;
this.stopBits = stopBits;
this.parity = parity;
this.deviceType = deviceType;
}
public int getVendorID() {
return vendorID;
}
public int getProductID() {
return productID;
}
public int getBaudRate() {
return baudRate;
}
public int getDataBits() {
return dataBits;
}
public int getStopBits() {
return stopBits;
}
public String getParity() {
return parity;
}
public DeviceType getDeviceType() {
return deviceType;
}
@Override
public String toString() {
return "SerialPort{" +
"vendorID='" + vendorID +
", productID=" + productID +
", baudRate=" + baudRate +
", dataBits=" + dataBits +
", stopBits=" + stopBits +
", parity='" + parity +
", deviceType=" + deviceType.getDescription() +
'}';
}
}

View File

@ -0,0 +1,97 @@
package com.unibuy.smartdevice.devices;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsEmptyException;
public enum SlotField {
VMC(0, false, true, true, true, true, true, true, true, true, true),
ELECTRIC(1, true, false, false, true, true, false, true, false, true, true),
;
public int getField() {
return field;
}
public boolean isCanAddPurchased() {
return isCanAddPurchased;
}
public boolean isCanOneShipped() {
return isCanOneShipped;
}
public boolean isInvoice() {
return isInvoice;
}
public boolean isDevNFCPay() {
return isDevNFCPay;
}
public boolean isDevEsunpay() {
return isDevEsunpay;
}
public boolean isDevTapPay() {
return isDevTapPay;
}
public boolean isDevCash() {
return isDevCash;
}
public boolean isDevLinePay() {
return isDevLinePay;
}
public boolean isAutoNextProduct() {
return isAutoNextProduct;
}
public boolean isAutoConfirm() {
return isAutoConfirm;
}
private Logs logs;
private int field;
private boolean isCanAddPurchased;
private boolean isCanOneShipped;
private boolean isInvoice;
private boolean isDevNFCPay;
private boolean isDevEsunpay;
private boolean isDevTapPay;
private boolean isDevCash;
private boolean isDevLinePay;
private boolean isAutoNextProduct;
private boolean isAutoConfirm;
SlotField(int field, boolean isCanAddPurchased, boolean isCanOneShipped, boolean isInvoice, boolean isDevNFCPay, boolean isDevEsunpay, boolean isDevTapPay, boolean isDevCash, boolean isDevLinePay, boolean isAutoNextProduct, boolean isAutoConfirm) {
this.logs = new Logs(getClass());
this.field = field;
this.isCanAddPurchased = isCanAddPurchased;
this.isCanOneShipped = isCanOneShipped;
this.isInvoice = isInvoice;
this.isDevNFCPay = isDevNFCPay;
this.isDevEsunpay = isDevEsunpay;
this.isDevTapPay = isDevTapPay;
this.isDevCash = isDevCash;
this.isDevLinePay = isDevLinePay;
this.isAutoNextProduct = isAutoNextProduct;
this.isAutoConfirm = isAutoConfirm;
}
public static SlotField getSlotField(int field) throws LogsEmptyException {
SlotField slotField = null;
for (SlotField slotFieldTmp: SlotField.values()) {
if (slotFieldTmp.getField() == field) {
slotField = slotFieldTmp;
break;
}
}
if (slotField != null) {
return slotField;
} else {
throw new LogsEmptyException(new Logs(SlotField.class), "Missing additional items");
}
}
}

View File

@ -0,0 +1,303 @@
package com.unibuy.smartdevice.devices;
import static com.unibuy.smartdevice.devices.PortTools.match;
import android.content.Context;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.util.Log;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsEmptyException;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class UsbDev {
private Logs logs;
private Context context;
private HashMap<String, UsbDevice> deviceList;
private UsbSerialPort usbSerialPort;
private static UsbManager usbManager;
public static void setUsbManager(Context context) {
usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
}
public static UsbManager getUsbManager() {
return usbManager;
}
public HashMap<String, UsbDevice> getDeviceList() {
return deviceList;
}
public UsbDev() throws LogsUnsupportedOperationException, LogsIOException {
this.logs = new Logs(this.getClass());
initDeviceList();
}
public UsbDev(DeviceType deviceType) throws LogsUnsupportedOperationException, LogsIOException, LogsEmptyException {
this();
connectPort(deviceType);
}
public UsbDev(SerialPort serialPort) throws LogsUnsupportedOperationException, LogsIOException, LogsEmptyException {
this();
connectPort(serialPort);
}
private void initDeviceList() throws LogsIOException, LogsUnsupportedOperationException {
Map<SerialPort, UsbDev> usbDeviceMap = new HashMap<>();
if (usbManager == null) {
throw new LogsIOException(logs, "UsbService not fund");
} else {
deviceList = usbManager.getDeviceList();
if (deviceList.isEmpty()) {
throw new LogsUnsupportedOperationException(logs, "initDeviceList:No USB devices connected");
}
}
}
private SerialPort getSerialPort(DeviceType deviceType) throws LogsEmptyException {
int vendorId = 0;
int productId = 0;
for (UsbDevice device : deviceList.values()) {
vendorId = device.getVendorId();
productId = device.getProductId();
SerialPort serialPort = SerialPort.getPortsByVendorInfo(vendorId, productId);
if (serialPort.getDeviceType().equals(deviceType)) {
logs.debug("getSerialPort vendorId:" + vendorId + " productId:" + productId + " deviceType:" + serialPort.getDeviceType() + " Ok");
return serialPort;
} else {
logs.debug("getSerialPort vendorId:" + vendorId + " productId:" + productId + " deviceType:" + serialPort.getDeviceType() + " No");
}
}
throw new LogsEmptyException(logs, "getSerialPort not found:" + deviceType.name());
}
private UsbDevice getDevice(DeviceType deviceType) throws LogsEmptyException {
return getDevice(getSerialPort(deviceType));
}
private UsbDevice getDevice(SerialPort serialPort) throws LogsEmptyException {
for (UsbDevice device : deviceList.values()) {
int vendorId = device.getVendorId();
int productId = device.getProductId();
logs.info("getDevice vendorId:"+vendorId+" productId:"+productId+" sp-vendorId:" + serialPort.getVendorID() + " sp-productId:" + serialPort.getProductID());
if (vendorId == serialPort.getVendorID() && productId == serialPort.getProductID()) {
return device;
}
}
throw new LogsEmptyException(logs, "getDevice Device not found:" + serialPort.getVendorID() + "/" + serialPort.getProductID());
}
public void connectPort(DeviceType deviceType) throws LogsEmptyException, LogsIOException {
SerialPort serialPort = getSerialPort(deviceType);
connectPort(serialPort);
}
public void connectPort(SerialPort serialPort) throws LogsEmptyException, LogsIOException {
logs.info("connectPort vendor id:" + serialPort.getVendorID() + " product id:" + serialPort.getProductID());
UsbDevice device = getDevice(serialPort);
if (UsbSerialProber.getDefaultProber().probeDevice(device) == null) {
logs.info("connectPort probeDevice(device) is null");
return;
}
for (UsbSerialPort usp : UsbSerialProber.getDefaultProber().probeDevice(device).getPorts()) {
logs.info("----- connectPort usp -----");
logs.info("connectPort usp DeviceName:" + usp.getDevice().getDeviceName());
logs.info("connectPort usp ProductName:" + usp.getDevice().getProductName());
}
usbSerialPort = UsbSerialProber.getDefaultProber().probeDevice(device).getPorts().get(0);
if (usbSerialPort == null) {
throw new LogsIOException(logs, "connectPort UsbSerialPort is null");
}
try {
usbSerialPort.open(usbManager.openDevice(device));
int parity = UsbSerialPort.PARITY_NONE;
if (serialPort.getParity().equals("EVEN")) {
parity = UsbSerialPort.PARITY_EVEN;
}
usbSerialPort.setParameters(serialPort.getBaudRate(), serialPort.getDataBits(), serialPort.getStopBits(), parity);
} catch (IOException e) {
throw new LogsIOException(logs, e.getLocalizedMessage());
}
}
public boolean moveToMatch(byte[] matchBytes, int moveLimit, int timeout) throws LogsIOException {
if (usbSerialPort == null) {
throw new LogsIOException(logs, "moveToMatch UsbSerialPort is null");
}
try {
byte[] buffer = new byte[1];
int size = 0;
int moveCount = 0;
while (moveCount <= moveLimit) {
size = usbSerialPort.read(buffer, timeout);
if (size == 1 && match(buffer[0], matchBytes)) {
return true;
}
moveCount++;
}
return false;
} catch (Exception e) {
throw new LogsIOException(logs, e.getLocalizedMessage());
}
}
public byte[] readToMatch(byte[] matchBytes, int readLimit, int timeout) throws LogsIOException {
if (usbSerialPort == null) {
throw new LogsIOException(logs, "readToMatch UsbSerialPort is null");
}
byte[] buffer = new byte[0];
try {
byte[] tmp = new byte[1];
int size = 0;
int moveCount = 0;
while (moveCount <= readLimit) {
size = usbSerialPort.read(buffer, timeout);
if (size == 1 && match(tmp[0], matchBytes)) {
return PortTools.subtractByteArrays(buffer, matchBytes.length-1);
}
buffer = PortTools.concatByteArrays(buffer, tmp);
moveCount++;
}
return buffer;
} catch (Exception e) {
throw new LogsIOException(logs, e.getLocalizedMessage());
}
}
public int read(byte[] buffer, int timeout) throws LogsUnsupportedOperationException, LogsIOException {
if (usbSerialPort == null) {
throw new LogsIOException(logs, "read UsbSerialPort is null");
}
try {
int size = usbSerialPort.read(buffer, timeout);
return size;
} catch (IOException e) {
throw new LogsIOException(logs, e);
}
}
public void send(byte[] buffer) throws LogsIOException {
if (usbSerialPort == null) {
throw new LogsIOException(logs, "send UsbSerialPort is null");
}
// 寫資料
Log.i("send buffer", PortTools.showHex(buffer));
try {
usbSerialPort.write(buffer, 1000);
} catch (IOException e) {
throw new LogsIOException(logs, e);
}
}
public int transmission(byte[] sendBuffer, byte[] readBuffer, int timeout) throws LogsIOException {
if (usbSerialPort == null) {
throw new LogsIOException(logs, "transmission UsbSerialPort is null");
}
try {
Log.i("send buffer", PortTools.showHex(sendBuffer));
usbSerialPort.write(sendBuffer, 1000);
// 讀資料
int size = usbSerialPort.read(readBuffer, timeout);
Log.i("read buffer", PortTools.showHex(readBuffer));
return size;
} catch (IOException e) {
throw new LogsIOException(logs, e);
}
}
public void closePort() throws LogsIOException {
if (usbSerialPort != null) {
try {
usbSerialPort.close();
} catch (IOException e) {
throw new LogsIOException(logs, e);
}
usbSerialPort = null;
}
}
public static void getDeviceInfo(Context context) throws LogsUnsupportedOperationException {
if (usbManager != null) {
Logs logs = new Logs(UsbDev.class);
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
if (deviceList.isEmpty()) {
throw new LogsUnsupportedOperationException(new Logs(context.getClass()), "getDeviceInfo:No USB devices connected");
}
for (UsbDevice device : deviceList.values()) {
logs.info("----- usb device -----");
int vendorId = device.getVendorId();
int productId = device.getProductId();
logs.info("Device Name: " + device.getDeviceName());
logs.info("Product Name: " + device.getProductName());
logs.info("Manufacturer Name: " + device.getManufacturerName());
logs.info("Vendor ID: " + vendorId);
logs.info("Product ID: " + productId);
logs.info(SerialPort.getPortsByVendorInfo(vendorId, productId).toString());
// logs.info("-----2-----");
// 列出所有介面資訊
// int interfaceCount = device.getInterfaceCount();
// logs.info("Number of Interfaces: " + interfaceCount);
//
// for (int i = 0; i < interfaceCount; i++) {
// UsbInterface usbInterface = device.getInterface(i);
// logs.info("Interface " + i + ":");
// logs.info(" Interface ID: " + usbInterface.getId());
// logs.info(" Interface Class: " + usbInterface.getInterfaceClass());
// logs.info(" Interface Subclass: " + usbInterface.getInterfaceSubclass());
// logs.info(" Interface Protocol: " + usbInterface.getInterfaceProtocol());
// logs.info("------------------");
//
// for (int j = 0; j < usbInterface.getEndpointCount(); j++) {
// UsbEndpoint endpoint = usbInterface.getEndpoint(j);
// logs.info(" Endpoint " + j + ":");
// logs.info(" Endpoint Address: " + endpoint.getAddress());
// logs.info(" Max Packet Size: " + endpoint.getMaxPacketSize());
// logs.info(" Endpoint Type: " + endpoint.getType());
// logs.info(" Direction: " +
// (endpoint.getDirection() == UsbConstants.USB_DIR_IN ? "IN" : "OUT"));
// logs.info("---------------------------");
// }
// }
}
} else {
throw new LogsUnsupportedOperationException(new Logs(context.getClass()), "UsbManager is not available");
}
}
}

View File

@ -0,0 +1,38 @@
package com.unibuy.smartdevice.exception;
public enum ErrorCode {
RE_OK(200, "ok"),
RE_ERROR(201, "error"),
MACHINE_DATA_EMPTY(301, "Machine data empty"),
DATA_NOT_FOUND(404, "Data not found"),
ENCODING_AND_DECODING_ERROR(405, "Encoding and decoding error"),
INVALID_URL_FORMAT(400, "Invalid URL format"),
JSON_FORMAT_ERROR(422, "Json format error"),
BAD_GATEWAY(502, "bad gateway"),
NETWORK_CONNECTION_ERROR(503, "Network connection error"),
DEV_ERROR(898, "device error"),
TIMEOUT(899, "Timeout"),
RESPONSE_CODE_ERROR(998, "response code error"),
NETWORK_UNKNOWN_ERROR(998, "Network unknown error"),
UNKNOWN_ERROR(999, "Unknown error"),
;
private final int code;
private final String message;
// Enum 的構造函數
ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
// 獲取錯誤代碼
public int getCode() {
return code;
}
// 獲取錯誤訊息
public String getMessage() {
return message;
}
}

View File

@ -0,0 +1,124 @@
package com.unibuy.smartdevice.exception;
import static android.content.Context.MODE_PRIVATE;
import android.content.Context;
import android.os.Environment;
import android.util.Log;
import com.unibuy.smartdevice.tools.Tools;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Logs {
private String message;
private String className;
private String methodName;
private int lineNumber;
public Logs(Class<?> clazz) {
this.message = "";
this.className = clazz.getSimpleName();
this.methodName = "";
this.lineNumber = 0;
}
public String getMessage() {
return this.message;
}
public String getClassName() {
return className;
}
public void writeFile(String data) {
File txtDebug = new File(Tools.getExternalFilesDir(), "debug.txt");
if (txtDebug.exists()) {
txtDebug.setReadable(true, false);
txtDebug.setWritable(true, false);
}
String dateTime = Tools.getTimeStampByNow("yyyy-MM-dd HH:mm:ss.SSS");
data = dateTime + " " + data;
try (FileOutputStream fos = new FileOutputStream(txtDebug, true)) { // try-with-resources 自動 close()
fos.write(data.getBytes());
fos.write("\n".getBytes()); // 換行
} catch (IOException e) {
warning(e);
}
}
public String getInfo() {
return this.className+"."+this.methodName+"("+this.lineNumber+")";
}
public void debug(String message) {
this.message = message;
Log.d(this.className, "DEBUG ["+getClassName()+"]"+this.message);
writeFile("DEBUG ["+getClassName()+"]"+this.message);
}
public void info(String message) {
this.message = message;
Log.i(this.className, "INFO ["+getClassName()+"]"+this.message);
writeFile("INFO ["+getClassName()+"]"+this.message);
}
public void ignore(Exception e) {
StackTraceElement[] stackTrace = e.getStackTrace();
if (stackTrace.length > 0) {
StackTraceElement element = stackTrace[0];
className = element.getClassName();
methodName = element.getMethodName();
lineNumber = element.getLineNumber();
}
ignore(e.getLocalizedMessage());
}
public void ignore(String message) {
this.message = message;
Log.w(this.className, "IGNORE ["+getClassName()+"/"+getInfo()+"]"+this.message);
writeFile("IGNORE ["+getClassName()+"/"+getInfo()+"]"+this.message);
}
public void warning(Exception e) {
StackTraceElement[] stackTrace = e.getStackTrace();
if (stackTrace.length > 0) {
StackTraceElement element = stackTrace[0];
className = element.getClassName();
methodName = element.getMethodName();
lineNumber = element.getLineNumber();
}
this.message = e.getLocalizedMessage();
Log.w(this.className, "WARNING ["+getInfo()+"]"+this.message);
writeFile("WARNING ["+getInfo()+"]"+this.message);
}
public void error(ErrorCode errorCode, String message) {
this.message = message;
Log.i(this.className, "ERROR ["+getClassName()+"("+errorCode.getCode()+")"+errorCode.getMessage()+"]"+this.message);
writeFile("ERROR ["+getClassName()+"("+errorCode.getCode()+")"+errorCode.getMessage()+"]"+this.message);
}
public void update(String key, String value) {
update(key, value, "");
}
public void update(String key, String value, String unit) {
this.message = value;
if (!unit.isEmpty()) this.message = this.message + " " + unit;
Log.w(this.className, "UPDATE ["+this.className+"]"+this.message);
writeFile("UPDATE ["+this.className+"]{\""+key+"\":\""+value+"\"}");
}
public void clearMessage() {
this.message = "";
}
}

View File

@ -0,0 +1,32 @@
package com.unibuy.smartdevice.exception;
public class LogsEmptyException extends LogsException {
public LogsEmptyException(Logs logs, String message) {
super(logs, message);
}
public LogsEmptyException(Logs logs, ErrorCode errorCode) {
super(logs, errorCode);
}
public LogsEmptyException(Logs logs, Throwable cause) {
super(logs, cause);
}
public LogsEmptyException(Logs logs, String message, ErrorCode errorCode) {
super(logs, message, errorCode);
}
public LogsEmptyException(Logs logs, String message, Throwable cause) {
super(logs, message, cause);
}
public LogsEmptyException(Logs logs, ErrorCode errorCode, Throwable cause) {
super(logs, errorCode, cause);
}
public LogsEmptyException(Logs logs, String message, ErrorCode errorCode, Throwable cause) {
super(logs, message, errorCode, cause);
}
}

View File

@ -0,0 +1,48 @@
package com.unibuy.smartdevice.exception;
import androidx.annotation.NonNull;
public class LogsException extends Exception {
private Logs logs;
private ErrorCode errorCode;
public ErrorCode getErrorCode() {
return errorCode;
}
public LogsException(Logs logs, String message) {
super(message);
this.logs = logs;
}
public LogsException(Logs logs, ErrorCode errorCode) {
this(logs, errorCode.getMessage());
this.errorCode = errorCode;
}
public LogsException(Logs logs, ErrorCode errorCode, String message) {
this(logs, errorCode.getMessage()+"/"+message);
this.errorCode = errorCode;
}
public LogsException(Logs logs, Throwable cause) {
this(logs, "e:"+cause.getMessage());
this.errorCode = ErrorCode.UNKNOWN_ERROR;
}
public LogsException(Logs logs, String message, ErrorCode errorCode) {
this(logs, message);
this.errorCode = errorCode;
}
public LogsException(Logs logs, String message, Throwable cause) {
this(logs, message+" e:"+cause.getMessage());
this.errorCode = ErrorCode.UNKNOWN_ERROR;
}
public LogsException(Logs logs, ErrorCode errorCode, Throwable cause) {
this(logs, "e:"+cause.getMessage());
this.errorCode = errorCode;
}
public LogsException(Logs logs, String message, ErrorCode errorCode, Throwable cause) {
this(logs, message+" e:"+cause.getMessage());
this.errorCode = errorCode;
}
public Logs getLogs() {
return logs;
}
}

View File

@ -0,0 +1,32 @@
package com.unibuy.smartdevice.exception;
public class LogsFileNullException extends LogsException {
public LogsFileNullException(Logs logs, String message) {
super(logs, message);
}
public LogsFileNullException(Logs logs, ErrorCode errorCode) {
super(logs, errorCode);
}
public LogsFileNullException(Logs logs, Throwable cause) {
super(logs, cause);
}
public LogsFileNullException(Logs logs, String message, ErrorCode errorCode) {
super(logs, message, errorCode);
}
public LogsFileNullException(Logs logs, String message, Throwable cause) {
super(logs, message, cause);
}
public LogsFileNullException(Logs logs, ErrorCode errorCode, Throwable cause) {
super(logs, errorCode, cause);
}
public LogsFileNullException(Logs logs, String message, ErrorCode errorCode, Throwable cause) {
super(logs, message, errorCode, cause);
}
}

View File

@ -0,0 +1,32 @@
package com.unibuy.smartdevice.exception;
public class LogsIOException extends LogsException {
public LogsIOException(Logs logs, String message) {
super(logs, message);
}
public LogsIOException(Logs logs, ErrorCode errorCode) {
super(logs, errorCode);
}
public LogsIOException(Logs logs, Throwable cause) {
super(logs, cause);
}
public LogsIOException(Logs logs, String message, ErrorCode errorCode) {
super(logs, message, errorCode);
}
public LogsIOException(Logs logs, String message, Throwable cause) {
super(logs, message, cause);
}
public LogsIOException(Logs logs, ErrorCode errorCode, Throwable cause) {
super(logs, errorCode, cause);
}
public LogsIOException(Logs logs, String message, ErrorCode errorCode, Throwable cause) {
super(logs, message, errorCode, cause);
}
}

View File

@ -0,0 +1,32 @@
package com.unibuy.smartdevice.exception;
public class LogsMalformedURLException extends LogsException {
public LogsMalformedURLException(Logs logs, String message) {
super(logs, message);
}
public LogsMalformedURLException(Logs logs, ErrorCode errorCode) {
super(logs, errorCode);
}
public LogsMalformedURLException(Logs logs, Throwable cause) {
super(logs, cause);
}
public LogsMalformedURLException(Logs logs, String message, ErrorCode errorCode) {
super(logs, message, errorCode);
}
public LogsMalformedURLException(Logs logs, String message, Throwable cause) {
super(logs, message, cause);
}
public LogsMalformedURLException(Logs logs, ErrorCode errorCode, Throwable cause) {
super(logs, errorCode, cause);
}
public LogsMalformedURLException(Logs logs, String message, ErrorCode errorCode, Throwable cause) {
super(logs, message, errorCode, cause);
}
}

View File

@ -0,0 +1,32 @@
package com.unibuy.smartdevice.exception;
public class LogsNoSuchElementException extends LogsException {
public LogsNoSuchElementException(Logs logs, String message) {
super(logs, message);
}
public LogsNoSuchElementException(Logs logs, ErrorCode errorCode) {
super(logs, errorCode);
}
public LogsNoSuchElementException(Logs logs, Throwable cause) {
super(logs, cause);
}
public LogsNoSuchElementException(Logs logs, String message, ErrorCode errorCode) {
super(logs, message, errorCode);
}
public LogsNoSuchElementException(Logs logs, String message, Throwable cause) {
super(logs, message, cause);
}
public LogsNoSuchElementException(Logs logs, ErrorCode errorCode, Throwable cause) {
super(logs, errorCode, cause);
}
public LogsNoSuchElementException(Logs logs, String message, ErrorCode errorCode, Throwable cause) {
super(logs, message, errorCode, cause);
}
}

View File

@ -0,0 +1,32 @@
package com.unibuy.smartdevice.exception;
public class LogsNullPointerException extends LogsException {
public LogsNullPointerException(Logs logs, String message) {
super(logs, message);
}
public LogsNullPointerException(Logs logs, ErrorCode errorCode) {
super(logs, errorCode);
}
public LogsNullPointerException(Logs logs, Throwable cause) {
super(logs, cause);
}
public LogsNullPointerException(Logs logs, String message, ErrorCode errorCode) {
super(logs, message, errorCode);
}
public LogsNullPointerException(Logs logs, String message, Throwable cause) {
super(logs, message, cause);
}
public LogsNullPointerException(Logs logs, ErrorCode errorCode, Throwable cause) {
super(logs, errorCode, cause);
}
public LogsNullPointerException(Logs logs, String message, ErrorCode errorCode, Throwable cause) {
super(logs, message, errorCode, cause);
}
}

View File

@ -0,0 +1,32 @@
package com.unibuy.smartdevice.exception;
public class LogsParseException extends LogsException {
public LogsParseException(Logs logs, String message) {
super(logs, message);
}
public LogsParseException(Logs logs, ErrorCode errorCode) {
super(logs, errorCode);
}
public LogsParseException(Logs logs, Throwable cause) {
super(logs, cause);
}
public LogsParseException(Logs logs, String message, ErrorCode errorCode) {
super(logs, message, errorCode);
}
public LogsParseException(Logs logs, String message, Throwable cause) {
super(logs, message, cause);
}
public LogsParseException(Logs logs, ErrorCode errorCode, Throwable cause) {
super(logs, errorCode, cause);
}
public LogsParseException(Logs logs, String message, ErrorCode errorCode, Throwable cause) {
super(logs, message, errorCode, cause);
}
}

View File

@ -0,0 +1,32 @@
package com.unibuy.smartdevice.exception;
public class LogsSecurityException extends LogsException {
public LogsSecurityException(Logs logs, String message) {
super(logs, message);
}
public LogsSecurityException(Logs logs, ErrorCode errorCode) {
super(logs, errorCode);
}
public LogsSecurityException(Logs logs, Throwable cause) {
super(logs, cause);
}
public LogsSecurityException(Logs logs, String message, ErrorCode errorCode) {
super(logs, message, errorCode);
}
public LogsSecurityException(Logs logs, String message, Throwable cause) {
super(logs, message, cause);
}
public LogsSecurityException(Logs logs, ErrorCode errorCode, Throwable cause) {
super(logs, errorCode, cause);
}
public LogsSecurityException(Logs logs, String message, ErrorCode errorCode, Throwable cause) {
super(logs, message, errorCode, cause);
}
}

View File

@ -0,0 +1,31 @@
package com.unibuy.smartdevice.exception;
public class LogsSettingEmptyException extends LogsException {
public LogsSettingEmptyException(Logs logs, String message) {
super(logs, message);
}
public LogsSettingEmptyException(Logs logs, ErrorCode errorCode) {
super(logs, errorCode);
}
public LogsSettingEmptyException(Logs logs, Throwable cause) {
super(logs, cause);
}
public LogsSettingEmptyException(Logs logs, String message, ErrorCode errorCode) {
super(logs, message, errorCode);
}
public LogsSettingEmptyException(Logs logs, String message, Throwable cause) {
super(logs, message, cause);
}
public LogsSettingEmptyException(Logs logs, ErrorCode errorCode, Throwable cause) {
super(logs, errorCode, cause);
}
public LogsSettingEmptyException(Logs logs, String message, ErrorCode errorCode, Throwable cause) {
super(logs, message, errorCode, cause);
}
}

View File

@ -0,0 +1,32 @@
package com.unibuy.smartdevice.exception;
public class LogsUnsupportedOperationException extends LogsException {
public LogsUnsupportedOperationException(Logs logs, String message) {
super(logs, message);
}
public LogsUnsupportedOperationException(Logs logs, ErrorCode errorCode) {
super(logs, errorCode);
}
public LogsUnsupportedOperationException(Logs logs, Throwable cause) {
super(logs, cause);
}
public LogsUnsupportedOperationException(Logs logs, String message, ErrorCode errorCode) {
super(logs, message, errorCode);
}
public LogsUnsupportedOperationException(Logs logs, String message, Throwable cause) {
super(logs, message, cause);
}
public LogsUnsupportedOperationException(Logs logs, ErrorCode errorCode, Throwable cause) {
super(logs, errorCode, cause);
}
public LogsUnsupportedOperationException(Logs logs, String message, ErrorCode errorCode, Throwable cause) {
super(logs, message, errorCode, cause);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,452 @@
package com.unibuy.smartdevice.external;
import android.content.Context;
import android.os.Bundle;
import android.os.Message;
import androidx.core.app.NotificationCompat;
import com.unibuy.smartdevice.MyApp;
import com.unibuy.smartdevice.exception.ErrorCode;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsParseException;
import com.unibuy.smartdevice.exception.LogsSettingEmptyException;
import com.unibuy.smartdevice.structure.GreenpayMerchantStructure;
import com.unibuy.smartdevice.structure.GreenpaySettingStructure;
import com.unibuy.smartdevice.tools.ApiPostMainScheduler;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.ui.dialog.CheckoutTapPayDialog;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class HttpTapPay {
public enum PayType {
LINE_PAY(30),
JKO_PAY(31),
EASY_PAY(32),
PI_PAY(33),
PLUS_PAY(34),
;
/*
myApp.PayType == 3 現金
myApp.PayType == 3 this.txtHint.setText("請掃描條碼");
myApp.PayType == 30 this.SwipeData = "LinePay";
myApp.PayType == 31 this.SwipeData = "街口支付";
myApp.PayType == 32 this.SwipeData = "悠遊付";
myApp.PayType == 33 this.SwipeData = "Pi拍錢包";
myApp.PayType == 34 this.SwipeData = "全盈+PAY";
*/
private int type;
public int getType() {
return type;
}
PayType(int type) {
this.type = type;
}
}
private Logs logs;
private Context context;
public final int ConnectTimeout = 4000;
public final int ReadTimeout = 30000;
public final String BACKEND_NOTIFY_URL_EXAMPLE = "https://example.com/back-end-notify";
public final String FRONTEND_REDIRECT_URL_EXAMPLE = "https://example.com/front-end-redirect";
private final String TAPPAY_DOMAIN = "https://prod.tappaysdk.com";
private final String TAPPAY_DOMAIN_SANDBOX = "https://sandbox.tappaysdk.com";
public final String TAPPAY_PAY_BY_PRIME_URL = "/tpc/payment/pay-by-prime";
private HandlerMain srcHandlerMain;
public HandlerMain getSrcHandlerMain() {
return srcHandlerMain;
}
public void checkMachineInfo() throws LogsSettingEmptyException {
if (MyApp.getInstance().getMachine().getApiKey().isEmpty() ||
MyApp.getInstance().getMachine().getMachineID().isEmpty()) {
throw new LogsSettingEmptyException(logs, "machine data empty");
}
}
// public final String TAPPAY_LINEPAY_RESULT_CALLBACK_URI = "linepayexample://tech.cherri";
// public String RESULT_CALLBACK_URI = TAPPAY_LINEPAY_RESULT_CALLBACK_URI;
// public final String TAPPAY_EasyWalle_RESULT_CALLBACK_URI = "ewexample://ew.app:8888/test";
// public final String TAPPAY_JkoPay_RESULT_CALLBACK_URI = "jkoexample://jko.uri:8888/test";
// public final String TAPPAY_PiWallet_RESULT_CALLBACK_URI = "piwalletexample://tech.cherri.piwalletexample";
// public final String TAPPAY_PlusPay_RESULT_CALLBACK_URI = "tpdirectexamplepluspay://tech.cherri/myaccount/detail";
//-------------- 設定 -----------------
// public String PARTNER_KEY = "partner_v1T5HZGz65di4GAMVAtvN6rCPzlpdDKNv3It1BNog0WTxPUgKG1S3KSq";
// public String APP_KEY = "app_F70rEjuAAyvj1BeJck9HeyF1EJTzdknTPmXMSlodZKwvM8PoniUMXbqP8l9m";
// public Integer APP_ID = 136289;
//-------------- 設定 -----------------
// public String CTBC_MERCHANT_ID = "wilson461973_CTBC"; //奇怪的帳號
// public String NCCC_MERCHANT_ID = "wilson461973_NCCC"; //奇怪的帳號
// public String TAISHIN_MERCHANT_ID = "wilson461973_TAISHIN"; //奇怪的帳號
// public String ESUN_MERCHANT_ID = "wilson461973_ESUN"; //奇怪的帳號
// public String GPUSD_MERCHANT_ID = "wilson461973_GP_USD_Only"; //奇怪的帳號
// public String LINE_MERCHANT_ID = "wilson461973_LINEPAY";
// public String JKO_MERCHANT_ID = "wilson461973_JKOPAY";
// public String EASY_MERCHANT_ID = "wilson461973_EASY_WALLET";
// public String PI_MERCHANT_ID = "wilson461973_PI_WALLET_Manual_CAP";
// public String PS_MERCHANT_ID = "wilson461973_PLUSPAY";
// public String DIRECT_MERCHANT_ID = "";
// public String APPLE_MERCHANT_ID = "";
// public String GOOGLE_MERCHANT_ID = "";
// public String SAMSUNG_MERCHANT_ID = "";
// public String ATOME_MERCHANT_ID = "";
// public static boolean isEnabled() {
// GreenpaySettingStructure greenpaySetting = MyApp.getInstance().getGreenpaySetting();
// GreenpayMerchantStructure greenpayMerchant = MyApp.getInstance().getGreenpayMerchant();
//
// boolean hasMerchantID = (greenpayMerchant.getLineMerchantId().isEmpty()
// && greenpayMerchant.getJkoMerchantId().isEmpty()
// && greenpayMerchant.getEasyMerchantId().isEmpty()
// && greenpayMerchant.getPiMerchantId().isEmpty()
// && greenpayMerchant.getPsMerchantId().isEmpty()
// && greenpayMerchant.getDirectMerchantId().isEmpty()
// && greenpayMerchant.getAppleMerchantId().isEmpty()
// && greenpayMerchant.getGoogleMerchantId().isEmpty()
// && greenpayMerchant.getSamsungMerchantId().isEmpty()
// && greenpayMerchant.getAtomeMerchantId().isEmpty()) ? false : true;
//
// return (!hasMerchantID
// || greenpaySetting.getPartnerKey().isEmpty()
// || greenpaySetting.getAppId().isEmpty()) ? false : true;
// }
public HttpTapPay(HandlerMain srcHandlerMain) {
this.logs = new Logs(this.getClass());
this.srcHandlerMain = srcHandlerMain;
}
private boolean isSandbox(String merchantId) {
return merchantId.contains("_LINEPAY") ||
merchantId.contains("_JKOPAY") ||
merchantId.contains("_EASY_WALLET") ||
merchantId.contains("_PI_WALLET") ||
merchantId.contains("_PLUSPAY") ||
merchantId.contains("_ATOME");
}
private String getUrlString(String urlString, String merchantId) {
String domainUrlString = isSandbox(merchantId) ? TAPPAY_DOMAIN_SANDBOX : TAPPAY_DOMAIN;
return domainUrlString + urlString;
}
// private void checkMachineInfo() throws LogsSettingEmptyException {
// if (MyApp.getInstance().getMachine().getApiKey().isEmpty() ||
// MyApp.getInstance().getMachine().getMachineID().isEmpty()) {
// throw new LogsSettingEmptyException(logs, "machine data empty");
// }
// }
/*
<item>Unibuy,https://unibuy.com.tw/Unibuy/api/app/,KahnEwjhfDBHUYS7,AAT</item>
<item>Beast,https://bkstore.com.tw/BeastKingdom/api/app/,KahnEwjhfDBHUYS7,野獸國</item>
<item>Lever,https://hysi.com.tw/lever/api/app/,KahnEwjhfDBHUYS7,銓寶</item>
<item>Love69,https://unibuy.com.tw/Love69sexy/api/app/,K232E91hHDBgUsx2,格子機</item>
<item>Test,http://hysi.com.tw/Unibuy/api/app/,KahnEwjhfDBHUYS7,測試版</item>
<item>Z0,https://unibuy.com.tw/Unibuy/api/app/,KahnEwjhfDBHUYS7,喜鵲[通行碼限定]</item>
<item>Z1,https://unibuy.com.tw/Unibuy/api/app/,KahnEwjhfDBHUYS7,喜鵲[香菸問卷]</item>
<item>Z2,https://unibuy.com.tw/Unibuy/api/app/,KahnEwjhfDBHUYS7,喜鵲[點數兌換]</item>
*/
// public String getPrimeUrlByWeb(int payType, String merchantId, String products, int totalPrice) {
// String urlString = getPrimeUrl(payType, merchantId, products, totalPrice);
//
// String timeStamp = new SimpleDateFormat("yyyyMMddhhmmss", Locale.US).format(new Date());
// String callBackStr = MyApp.getInstance().getMachine().getMachineID() + timeStamp;
// urlString += "&order_number=" + callBackStr;
//
// return urlString;
// }
public String getPrimeUrl(String products, int totalPrice) throws LogsSettingEmptyException {
checkMachineInfo();
String owner = "AAT";
int payType = MyApp.getInstance().getReportFlowInfoData().getFlowType();
GreenpaySettingStructure greenpaySetting = MyApp.getInstance().getGreenpaySetting();
String greenpayMerchantId = MyApp.getInstance().getMachine().getMachineID();
logs.info("aaaaaaaaaaaaaaaaaaaaaa1"+ MyApp.getInstance().getGreenpayMerchant().getLineMerchantId());
logs.info("aaaaaaaaaaaaaaaaaaaaaa2"+ MyApp.getInstance().getGreenpayMerchant().getJkoMerchantId());
logs.info("aaaaaaaaaaaaaaaaaaaaaa3"+ MyApp.getInstance().getGreenpayMerchant().getPiMerchantId());
logs.info("aaaaaaaaaaaaaaaaaaaaaa4"+ MyApp.getInstance().getGreenpayMerchant().getPsMerchantId());
logs.info("aaaaaaaaaaaaaaaaaaaaaa5"+ MyApp.getInstance().getGreenpayMerchant().getEasyMerchantId());
switch (payType) {
case 30:
if (MyApp.getInstance().getGreenpayMerchant() != null && !MyApp.getInstance().getGreenpayMerchant().getLineMerchantId().isEmpty()) {
greenpayMerchantId = MyApp.getInstance().getGreenpayMerchant().getLineMerchantId();
} else {
return "";
}
break;
case 31:
if (MyApp.getInstance().getGreenpayMerchant() != null && !MyApp.getInstance().getGreenpayMerchant().getJkoMerchantId().isEmpty()) {
greenpayMerchantId = MyApp.getInstance().getGreenpayMerchant().getJkoMerchantId();
} else {
return "";
}
break;
case 32:
if (MyApp.getInstance().getGreenpayMerchant() != null && !MyApp.getInstance().getGreenpayMerchant().getEasyMerchantId().isEmpty()) {
greenpayMerchantId = MyApp.getInstance().getGreenpayMerchant().getEasyMerchantId();
} else {
return "";
}
break;
case 33:
if (MyApp.getInstance().getGreenpayMerchant() != null && !MyApp.getInstance().getGreenpayMerchant().getPiMerchantId().isEmpty()) {
greenpayMerchantId = MyApp.getInstance().getGreenpayMerchant().getPiMerchantId();
} else {
return "";
}
break;
case 34:
if (MyApp.getInstance().getGreenpayMerchant() != null && !MyApp.getInstance().getGreenpayMerchant().getPsMerchantId().isEmpty()) {
greenpayMerchantId = MyApp.getInstance().getGreenpayMerchant().getPsMerchantId();
} else {
return "";
}
break;
default:
logs.info("未設定TapPay商店代碼" + payType);
return "";
}
StringBuilder s = new StringBuilder("");
//s.append("https://unibuy.com.tw/tools/bROPi9rxqM6EyxBd.html");
s.append("https://unibuy.com.tw/chi-hai/tools/bROPi9rxqM6EyxBd.html");
s.append("?key=");
s.append(MyApp.getInstance().getMachine().getApiKey());
s.append("&partner_key=");
s.append(greenpaySetting.getPartnerKey());
s.append("&APP_KEY=");
s.append(greenpaySetting.getAppKey());
s.append("&APP_ID=");
s.append(greenpaySetting.getAppId());
s.append("&merchant_id=");
s.append(greenpayMerchantId); //廠商ID
s.append("&SERVER_TYPE=");
s.append(isSandbox(greenpayMerchantId) ? "sandbox" : "production");
s.append("&details=");
s.append(products.replace("\"", "\\\"")); //產品名稱
s.append("&amount=");
s.append(totalPrice); //總金額
s.append("&type=");
s.append(payType);
if (owner.equals("Beast")) {
s.append("&api_type=1"); //野獸國自己的平台
} else {
s.append("&api_type=0"); //AAT自己的平台
}
s.append("&order_number=");
s.append(MyApp.getInstance().getReportFlowInfoData().getOrderId());
logs.info("prime:" + s.toString());
return s.toString();
}
/*
myApp.PayType == 3 現金
myApp.PayType == 3 this.txtHint.setText("請掃描條碼");
myApp.PayType == 30 this.SwipeData = "LinePay";
myApp.PayType == 31 this.SwipeData = "街口支付";
myApp.PayType == 32 this.SwipeData = "悠遊付";
myApp.PayType == 33 this.SwipeData = "Pi拍錢包";
myApp.PayType == 34 this.SwipeData = "全盈+PAY";
*/
public void newOrder(String products, int totalPrice, ApiPostMainScheduler apiPostRunMain) throws LogsParseException, LogsSettingEmptyException {
checkMachineInfo();
String phone = "";
String prime = getPrimeUrl(products, totalPrice);
try {
// String timeStamp = new SimpleDateFormat("yyyyMMddhhmmss", Locale.US).format(new Date());
JSONObject jsonObject = new JSONObject();
jsonObject.put("prime", prime);
jsonObject.put("partner_key", MyApp.getInstance().getGreenpaySetting().getPartnerKey());
jsonObject.put("merchant_id", MyApp.getInstance().getMachine().getMachineID());
jsonObject.put("order_number", MyApp.getInstance().getReportFlowInfoData().getOrderId());
jsonObject.put("details", products);
jsonObject.put("amount", totalPrice);
JSONObject cardHolderJO = new JSONObject();
cardHolderJO.put("phone_number", phone);
cardHolderJO.put("name", "");
cardHolderJO.put("email", "");
jsonObject.put("cardholder", cardHolderJO);
JSONObject resultUrlJO = new JSONObject();
resultUrlJO.put("frontend_redirect_url", FRONTEND_REDIRECT_URL_EXAMPLE);
resultUrlJO.put("backend_notify_url", BACKEND_NOTIFY_URL_EXAMPLE);
jsonObject.put("result_url", resultUrlJO);
logs.info("json:" + jsonObject.toString());
apiPostRunMain.start(getUrlString(TAPPAY_PAY_BY_PRIME_URL, MyApp.getInstance().getMachine().getMachineID()), jsonObject.toString(), null, null);
} catch (JSONException e) {
throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR);
}
}
// public void doRefund(String tradeID, String merchant_id, ApiPostMainScheduler apiPostMainScheduler) throws JSONException {
// JSONObject jsonObject = new JSONObject();
// jsonObject.put("partner_key", MyApp.getInstance().getGreenpaySetting().getPartnerKey());
// jsonObject.put("rec_trade_id", tradeID);
// apiPostMainScheduler.start(getUrlString("/tpc/transaction/refund", merchant_id), jsonObject.toString(), null, null);
// }
public void getRecord() throws LogsParseException, LogsSettingEmptyException {
getRecord(new ApiPostMainScheduler(getSrcHandlerMain()) {
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected Class<?> setCls() {
return getClass();
}
@Override
public void response(int responseCode, String receive, HandlerMain handlerMain) {
if (responseCode == 200) {
try {
JSONObject jsonObjectByReceive = new JSONObject(receive);
getLogs().info(jsonObjectByReceive.toString());
if (jsonObjectByReceive.getInt(NotificationCompat.CATEGORY_STATUS) == 2) {
if (jsonObjectByReceive.getInt("number_of_transactions") == 0) {
//五秒後重新詢問
getSrcHandlerMain().send(getClass().getSimpleName(), CheckoutTapPayDialog.Option.TRANSACTION_AGAIN.getOption(), "五秒後再次查詢");
return;
}
JSONObject j = jsonObjectByReceive.getJSONArray("trade_records").getJSONObject(0);
int n = j.getInt("record_status");
switch (n) {
case -1:
//TapPay交易錯誤
getSrcHandlerMain().send(getClass().getSimpleName(), CheckoutTapPayDialog.Option.TRANSACTION_FAILED.getOption(), "TRANSACTION_SUCCESSFUL");
break;
case 0:
case 1:
//付款成功
String message = j.toString().replace("\t", "");
getSrcHandlerMain().send(getClass().getSimpleName(), CheckoutTapPayDialog.Option.TRANSACTION_SUCCESSFUL.getOption(), message);
return;
case 2:
//TapPay部分退款
getSrcHandlerMain().send(getClass().getSimpleName(), CheckoutTapPayDialog.Option.TRANSACTION_FAILED.getOption(), "TapPay部分退款");
break;
case 3:
//TapPay完全退款
getSrcHandlerMain().send(getClass().getSimpleName(), CheckoutTapPayDialog.Option.TRANSACTION_FAILED.getOption(), "TapPay完全退款");
break;
case 4:
//五秒後重新詢問
getSrcHandlerMain().send(getClass().getSimpleName(), CheckoutTapPayDialog.Option.TRANSACTION_AGAIN.getOption(), "五秒後再次查詢");
return;
case 5:
//TapPay取消付款
getSrcHandlerMain().send(getClass().getSimpleName(), CheckoutTapPayDialog.Option.TRANSACTION_FAILED.getOption(), "TapPay取消付款");
break;
default:
//TapPay(" + n + ")"
getSrcHandlerMain().send(getClass().getSimpleName(), CheckoutTapPayDialog.Option.TRANSACTION_FAILED.getOption(), "TapPay(\" + n + \")\"");
break;
}
}
} catch (JSONException e) {
getLogs().error(ErrorCode.JSON_FORMAT_ERROR, e.getLocalizedMessage());
}
}
}
});
}
private void getRecord(ApiPostMainScheduler apiPostMainScheduler) throws LogsParseException, LogsSettingEmptyException {
checkMachineInfo();
try {
String merchantId = MyApp.getInstance().getMachine().getMachineID();
JSONObject jsonObject = new JSONObject();
jsonObject.put("partner_key", MyApp.getInstance().getGreenpaySetting().getPartnerKey());
JSONObject filtersJO = new JSONObject();
filtersJO.put("order_number", MyApp.getInstance().getReportFlowInfoData().getOrderId());
// Date dt = new Date();
// dt.setTime(1698905493742L);
// JSONObject timeJO = new JSONObject();
// timeJO.put("start_time", 1698905493742L - 3000000);
// timeJO.put("end_time", 3000000 + 1698905493742L);
Date dt = new Date();
long baseTime = dt.getTime(); // 取得現在的毫秒時間
long thirtyMinutesMillis = 30 * 60 * 1000; // 30分鐘 = 1800000 毫秒
JSONObject timeJO = new JSONObject();
timeJO.put("start_time", baseTime - thirtyMinutesMillis); // 30分鐘前
timeJO.put("end_time", baseTime + thirtyMinutesMillis); // 30分鐘後
jsonObject.put("time", timeJO);
jsonObject.put("filters", filtersJO);
Map<String, String> mapByRequestProperty = new HashMap<>();
mapByRequestProperty.put("x-api-key", MyApp.getInstance().getGreenpaySetting().getPartnerKey());
apiPostMainScheduler.start(getUrlString("/tpc/transaction/query", merchantId), jsonObject.toString(), null, null, mapByRequestProperty);
} catch (JSONException e) {
throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR);
}
}
public void getRecord(String orderNumber) throws LogsSettingEmptyException, JSONException {
getRecord(orderNumber, new ApiPostMainScheduler(getSrcHandlerMain()) {
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected Class<?> setCls() {
return getClass();
}
@Override
public void response(int responseCode, String receive, HandlerMain handlerMain) {
if (responseCode == 200) {
try {
JSONObject jsonObject = new JSONObject(receive);
if (jsonObject.getInt(NotificationCompat.CATEGORY_STATUS) == 2) {
jsonObject.getJSONArray("trade_records").getJSONObject(0);
}
} catch (JSONException e) {
getLogs().error(ErrorCode.JSON_FORMAT_ERROR, e.getLocalizedMessage());
}
}
}
});
}
private void getRecord(String orderNumber, ApiPostMainScheduler apiPostMainScheduler) throws JSONException, LogsSettingEmptyException {
checkMachineInfo();
String merchantId = MyApp.getInstance().getMachine().getMachineID();
JSONObject jsonObject = new JSONObject();
jsonObject.put("partner_key", MyApp.getInstance().getGreenpaySetting().getPartnerKey());
JSONObject filtersJO = new JSONObject();
filtersJO.put("order_number", orderNumber);
long now = new Date().getTime();
JSONObject timeJO = new JSONObject();
timeJO.put("start_time", now - 300000);
timeJO.put("end_time", now);
jsonObject.put("time", timeJO);
jsonObject.put("filters", filtersJO);
apiPostMainScheduler.start(getUrlString("/tpc/transaction/query", merchantId), jsonObject.toString(), null, null);
}
}

View File

@ -0,0 +1,17 @@
package com.unibuy.smartdevice.structure;
public class AccessCodeStructure {
private String passCode;
public AccessCodeStructure(String passCode) {
this.passCode = passCode;
}
public String getPassCode() {
return passCode;
}
public void setPassCode(String passCode) {
this.passCode = passCode;
}
}

View File

@ -0,0 +1,94 @@
package com.unibuy.smartdevice.structure;
public class BuyStructure {
private int field;
private int slot;
private ProductStructure product;
private int count;
private boolean isMarketingPlan;
private boolean isFreeGift;
/*
JSONObject jsonObject = new JSONObject();
jsonObject.put("key", apiKey);
jsonObject.put("machine", MachineName);
jsonObject.put("tid", trackID + "");
jsonObject.put(TPDNetworkConstants.ARG_SAMSUNG_PAY_PRIME_TYPE, type);
String receive = DoPut(DomainName + "products/exp/B025", jsonObject.toString());
*/
public BuyStructure(int field, int slot, ProductStructure product, int count) {
this.field = field;
this.slot = slot;
this.product = product;
this.count = count;
this.isMarketingPlan = false;
this.isFreeGift = false;
}
public int getField() {
return field;
}
public void setField(int field) {
this.field = field;
}
public int getSlot() {
return this.slot;
}
public void setSlot(int slot) {
this.slot = slot;
}
public ProductStructure getProduct() {
return this.product;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public void setProduct(ProductStructure product) {
this.product = product;
}
public int getFullPrice() {
int count = getCount();
int price = getProduct().getRealPrice();
return count * price;
}
public boolean isMarketingPlan() {
return isMarketingPlan;
}
public void setMarketingPlan(boolean marketingPlan) {
isMarketingPlan = marketingPlan;
}
public boolean isFreeGift() {
return isFreeGift;
}
public void setFreeGift(boolean freeGift) {
isFreeGift = freeGift;
}
@Override
public String toString() {
return "BuyStructure{" +
"field=" + field +
", slot=" + slot +
", product=" + (product != null ? product.toString() : "null") +
", count=" + count +
", fullPrice=" + getFullPrice() +
", isMarketingPlan=" + isMarketingPlan() +
", isFreeGift=" + isFreeGift() +
'}';
}
}

View File

@ -0,0 +1,121 @@
package com.unibuy.smartdevice.structure;
public class CashSetStructure {
private boolean billF1000;
private boolean billE500;
private boolean billD100;
private boolean coinF50;
private boolean coinE10;
private boolean coinD5;
private boolean coinC1;
public CashSetStructure(boolean billF1000, boolean billE500, boolean billD100, boolean coinF50, boolean coinE10, boolean coinD5, boolean coinC1) {
this.billF1000 = billF1000;
this.billE500 = billE500;
this.billD100 = billD100;
this.coinF50 = coinF50;
this.coinE10 = coinE10;
this.coinD5 = coinD5;
this.coinC1 = coinC1;
}
public boolean isBillF1000() {
return billF1000;
}
public void setBillF1000(boolean billF1000) {
this.billF1000 = billF1000;
}
public boolean isBillE500() {
return billE500;
}
public void setBillE500(boolean billE500) {
this.billE500 = billE500;
}
public boolean isBillD100() {
return billD100;
}
public void setBillD100(boolean billD100) {
this.billD100 = billD100;
}
public boolean isCoinF50() {
return coinF50;
}
public void setCoinF50(boolean coinF50) {
this.coinF50 = coinF50;
}
public boolean isCoinE10() {
return coinE10;
}
public void setCoinE10(boolean coinE10) {
this.coinE10 = coinE10;
}
public boolean isCoinD5() {
return coinD5;
}
public void setCoinD5(boolean coinD5) {
this.coinD5 = coinD5;
}
public boolean isCoinC1() {
return coinC1;
}
public void setCoinC1(boolean coinC1) {
this.coinC1 = coinC1;
}
public byte getByteByCoin1() {
return 0x00;
}
public byte getByteByCoin2() {
int u = 0;
if (isCoinC1()) {
u |= 1;
};
if (isCoinD5()) {
u |= 2;
}
if (isCoinE10()) {
u |= 4;
}
if (isCoinF50()) {
u |= 8;
}
return (byte) u;
}
public byte getByteByBill1() {
return 0x00;
}
public byte getByteByBill2() {
int u = 0;
if (isBillD100()) {
u |= 1;
}
u |= 2;
if (isBillE500()) {
u |= 4;
}
if (isBillF1000()) {
u |= 8;
}
return (byte) u;
}
}

View File

@ -0,0 +1,89 @@
package com.unibuy.smartdevice.structure;
public class CreditCardReceiptStructure {
private String MarchantNo;
private int TerminalNo;
private String CardType;
private String CardNo;
private String TransType;
private String BatchNo;
private String AuthCode;
private String DateTime;
private String InvNo;
private int CCRAmount;
public CreditCardReceiptStructure(String MarchantNo, int TerminalNo, String CardType, String CardNo
, String TransType, String BatchNo, String AuthCode, String DateTime, String InvNo, int CCRAmount) {
this.MarchantNo = MarchantNo;
this.TerminalNo = TerminalNo;
this.CardType = CardType;
this.CardNo = CardNo;
this.TransType = TransType;
this.BatchNo = BatchNo;
this.AuthCode = AuthCode;
this.DateTime = DateTime;
this.InvNo = InvNo;
this.CCRAmount = CCRAmount;
}
public String getMarchantNo() {
return MarchantNo;
}
public void setMarchantNo(String MarchantNo) {
this.MarchantNo = MarchantNo;
}
public int getTerminalNo() {
return this.TerminalNo;
}
public void setTerminalNo(int TerminalNo) {
this.TerminalNo = TerminalNo;
}
public String getCardType() {
return CardType;
}
public void setCardType(String CardType) {
this.CardType = CardType;
}
public String getCardNo() {
return CardNo;
}
public void setCardNo(String CardNo) {
this.CardNo = CardNo;
}
public String getTransType() {
return TransType;
}
public void setTransType(String TransType) {
this.TransType = TransType;
}
public String getBatchNo() {
return BatchNo;
}
public void setBatchNo(String BatchNo) {
this.BatchNo = BatchNo;
}
public String getAuthCode() {
return AuthCode;
}
public void setAuthCode(String AuthCode) {
this.AuthCode = AuthCode;
}
public String getDateTime() {
return DateTime;
}
public void setDateTime(String DateTime) {
this.DateTime = DateTime;
}
public String getInvNo() {
return InvNo;
}
public void setInvNo(String InvNo) {
this.InvNo = InvNo;
}
public int getCCRAmount() {
return CCRAmount;
}
public void setCCRAmount(int CCRAmount) {
this.CCRAmount = CCRAmount;
}
}

View File

@ -0,0 +1,127 @@
package com.unibuy.smartdevice.structure;
public class DevSetStructure {
private boolean isVMC;
private boolean isElectic;
private boolean isShoppingCar;
private boolean isInvoice;
private boolean isDevNFCPay;
private boolean isDevEsunPay;
private boolean isDevTapPay;
private boolean isDevCash;
private boolean isDevLinePay;
private boolean isTapPay30;
private boolean isTapPay31;
private boolean isTapPay32;
private boolean isTapPay33;
private boolean isTapPay34;
public DevSetStructure(boolean isVMC, boolean isElectic, boolean isShoppingCar, boolean isInvoice,
boolean isDevNFCPay, boolean isDevEsunPay, boolean isDevTapPay, boolean isDevCash, boolean isDevLinePay,
boolean isTapPay30,boolean isTapPay31,boolean isTapPay32,boolean isTapPay33, boolean isTapPay34) {
this.isVMC = isVMC;
this.isElectic = isElectic;
this.isShoppingCar = isShoppingCar;
this.isInvoice = isInvoice;
this.isDevNFCPay = isDevNFCPay;
this.isDevEsunPay = isDevEsunPay;
this.isDevTapPay = isDevTapPay;
this.isDevCash = isDevCash;
this.isDevLinePay = isDevLinePay;
this.isTapPay30 = isTapPay30;
this.isTapPay31 = isTapPay31;
this.isTapPay32 = isTapPay32;
this.isTapPay33 = isTapPay33;
this.isTapPay34 = isTapPay34;
}
public boolean isVMC() {
return isVMC;
}
public boolean isElectic() {
return isElectic;
}
public boolean isShoppingCar() {
return isShoppingCar;
}
public boolean isInvoice() {
return isInvoice;
}
public boolean isDevNFCPay() {
return isDevNFCPay;
}
public boolean isDevEsunPay() {
return isDevEsunPay;
}
public boolean isDevTapPay() { return isDevTapPay; }
public boolean isDevCash() {
return isDevCash;
}
public boolean isDevLinePay() {
return isDevLinePay;
}
public boolean isTapPay30() {
return isTapPay30;
}
public boolean isTapPay31() {
return isTapPay31;
}
public boolean isTapPay32() {
return isTapPay32;
}
public boolean isTapPay33() {
return isTapPay33;
}
public boolean isTapPay34() {
return isTapPay34;
}
public void setVMC(boolean VMC) {
isVMC = VMC;
}
public void setElectic(boolean electic) {
isElectic = electic;
}
public void setShoppingCar(boolean shoppingCar) {
isShoppingCar = shoppingCar;
}
public void setInvoice(boolean invoice) {
isInvoice = invoice;
}
public void setDevNFCPay(boolean devNFCPay) {
isDevNFCPay = devNFCPay;
}
public void setDevEsunPay(boolean devEsunPay) {
isDevEsunPay = devEsunPay;
}
public void setDevTapPay(boolean devTapPay) {
isDevTapPay = devTapPay;
}
public void setDevCash(boolean devCash) {
isDevCash = devCash;
}
public void setDevLinePay(boolean devLinePay) {isDevLinePay = devLinePay;}
public void setTapPay30(boolean tapPay30) {isTapPay30 = tapPay30;}
public void setTapPay31(boolean tapPay31) {isTapPay31 = tapPay31;}
public void setTapPay32(boolean tapPay32) {isTapPay32 = tapPay32;}
public void setTapPay33(boolean tapPay33) {isTapPay33 = tapPay33;}
public void setTapPay34(boolean tapPay34) {isTapPay34 = tapPay34;}
}

View File

@ -0,0 +1,84 @@
package com.unibuy.smartdevice.structure;
public class DispatchStructure {
private int field;
private int slot;
private ProductStructure product;
private int count;
private int quantity;
private boolean isShipped;
private boolean isFreeGift;
private boolean isGetProductComplete = false;
public DispatchStructure(int field, int slot, ProductStructure product, int quantity) {
this.field = field;
this.slot = slot;
this.product = product;
this.count = 0;
this.quantity = quantity;
this.isShipped = false;
this.isFreeGift = false;
}
public int getField() {
return field;
}
public void setField(int field) {
this.field = field;
}
public int getSlot() {
return this.slot;
}
public void setSlot(int slot) {
this.slot = slot;
}
public ProductStructure getProduct() {
return this.product;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public void setProduct(ProductStructure product) {
this.product = product;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public boolean isShipped() {
return isShipped;
}
public void setShipped(boolean shipped) {
isShipped = shipped;
}
public boolean isFreeGift() {
return isFreeGift;
}
public void setFreeGift(boolean freeGift) {
isFreeGift = freeGift;
}
public boolean isGetProductComplete() {
return isGetProductComplete;
}
public void setGetProductComplete(boolean getProductComplete) {
isGetProductComplete = getProductComplete;
}
}

View File

@ -0,0 +1,37 @@
package com.unibuy.smartdevice.structure;
public class EsunpayStructure {
private String storeID;
private String termID;
private String hash;
public EsunpayStructure(String storeID, String termID, String hash) {
this.storeID = storeID;
this.termID = termID;
this.hash = hash;
}
public String getStoreID() {
return storeID;
}
public void setStoreID(String storeID) {
this.storeID = storeID;
}
public String getTermID() {
return termID;
}
public void setTermID(String termID) {
this.termID = termID;
}
public String getHash() {
return hash;
}
public void setHash(String hash) {
this.hash = hash;
}
}

View File

@ -0,0 +1,17 @@
package com.unibuy.smartdevice.structure;
public class FreeGiftStructure {
private String passCode;
public FreeGiftStructure(String passCode) {
this.passCode = passCode;
}
public String getPassCode() {
return passCode;
}
public void setPassCode(String passCode) {
this.passCode = passCode;
}
}

View File

@ -0,0 +1,47 @@
package com.unibuy.smartdevice.structure;
public class GreenInvoiceStructure {
private String greenMerchantID;
private String greenHashKey;
private String greenHashIV;
private String greenEmail;
public String getGreenMerchantID() {
return greenMerchantID;
}
public void setGreenMerchantID(String greenMerchantID) {
this.greenMerchantID = greenMerchantID;
}
public String getGreenHashKey() {
return greenHashKey;
}
public void setGreenHashKey(String greenHashKey) {
this.greenHashKey = greenHashKey;
}
public String getGreenHashIV() {
return greenHashIV;
}
public void setGreenHashIV(String greenHashIV) {
this.greenHashIV = greenHashIV;
}
public String getGreenEmail() {
return greenEmail;
}
public void setGreenEmail(String greenEmail) {
this.greenEmail = greenEmail;
}
public GreenInvoiceStructure(String greenMerchantID, String greenHashKey, String greenHashIV, String greenEmail) {
this.greenMerchantID = greenMerchantID;
this.greenHashKey = greenHashKey;
this.greenHashIV = greenHashIV;
this.greenEmail = greenEmail;
}
}

View File

@ -0,0 +1,107 @@
package com.unibuy.smartdevice.structure;
public class GreenpayMerchantStructure {
private String lineMerchantId;
private String psMerchantId;
private String easyMerchantId;
private String piMerchantId;
private String jkoMerchantId;
private String directMerchantId;
private String appleMerchantId;
private String googleMerchantId;
private String samsungMerchantId;
private String atomeMerchantId;
public GreenpayMerchantStructure(String lineMerchantId, String psMerchantId, String easyMerchantId, String piMerchantId, String jkoMerchantId, String directMerchantId, String appleMerchantId, String googleMerchantId, String samsungMerchantId, String atomeMerchantId) {
this.lineMerchantId = lineMerchantId;
this.psMerchantId = psMerchantId;
this.easyMerchantId = easyMerchantId;
this.piMerchantId = piMerchantId;
this.jkoMerchantId = jkoMerchantId;
this.directMerchantId = directMerchantId;
this.appleMerchantId = appleMerchantId;
this.googleMerchantId = googleMerchantId;
this.samsungMerchantId = samsungMerchantId;
this.atomeMerchantId = atomeMerchantId;
}
public String getLineMerchantId() {
return lineMerchantId;
}
public String getPsMerchantId() {
return psMerchantId;
}
public String getEasyMerchantId() {
return easyMerchantId;
}
public String getPiMerchantId() {
return piMerchantId;
}
public String getJkoMerchantId() {
return jkoMerchantId;
}
public String getDirectMerchantId() {
return directMerchantId;
}
public String getAppleMerchantId() {
return appleMerchantId;
}
public String getGoogleMerchantId() {
return googleMerchantId;
}
public String getSamsungMerchantId() {
return samsungMerchantId;
}
public String getAtomeMerchantId() {
return atomeMerchantId;
}
public void setLineMerchantId(String lineMerchantId) {
this.lineMerchantId = lineMerchantId;
}
public void setPsMerchantId(String psMerchantId) {
this.psMerchantId = psMerchantId;
}
public void setEasyMerchantId(String easyMerchantId) {
this.easyMerchantId = easyMerchantId;
}
public void setPiMerchantId(String piMerchantId) {
this.piMerchantId = piMerchantId;
}
public void setJkoMerchantId(String jkoMerchantId) {
this.jkoMerchantId = jkoMerchantId;
}
public void setDirectMerchantId(String directMerchantId) {
this.directMerchantId = directMerchantId;
}
public void setAppleMerchantId(String appleMerchantId) {
this.appleMerchantId = appleMerchantId;
}
public void setGoogleMerchantId(String googleMerchantId) {
this.googleMerchantId = googleMerchantId;
}
public void setSamsungMerchantId(String samsungMerchantId) {
this.samsungMerchantId = samsungMerchantId;
}
public void setAtomeMerchantId(String atomeMerchantId) {
this.atomeMerchantId = atomeMerchantId;
}
}

View File

@ -0,0 +1,87 @@
package com.unibuy.smartdevice.structure;
public class GreenpaySettingStructure {
private String appId;
private String appKey;
private String partnerKey;
private String ctbcMerchantId;
private String ncccMerchantId;
private String taishinMerchantId;
private String esunMerchantId;
private String gpuseMerchantId;
public GreenpaySettingStructure(String appId, String appKey, String partnerKey, String ctbcMerchantId, String ncccMerchantId, String taishinMerchantId, String esunMerchantId, String gpuseMerchantId) {
this.appId = appId;
this.appKey = appKey;
this.partnerKey = partnerKey;
this.ctbcMerchantId = ctbcMerchantId;
this.ncccMerchantId = ncccMerchantId;
this.taishinMerchantId = taishinMerchantId;
this.esunMerchantId = esunMerchantId;
this.gpuseMerchantId = gpuseMerchantId;
}
public String getAppId() {
return appId;
}
public String getAppKey() {
return appKey;
}
public String getPartnerKey() {
return partnerKey;
}
public String getCtbcMerchantId() {
return ctbcMerchantId;
}
public String getNcccMerchantId() {
return ncccMerchantId;
}
public String getTaishinMerchantId() {
return taishinMerchantId;
}
public String getEsunMerchantId() {
return esunMerchantId;
}
public String getGpuseMerchantId() {
return gpuseMerchantId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public void setAppKey(String appKey) {
this.appKey = appKey;
}
public void setPartnerKey(String partnerKey) {
this.partnerKey = partnerKey;
}
public void setCtbcMerchantId(String ctbcMerchantId) {
this.ctbcMerchantId = ctbcMerchantId;
}
public void setNcccMerchantId(String ncccMerchantId) {
this.ncccMerchantId = ncccMerchantId;
}
public void setTaishinMerchantId(String taishinMerchantId) {
this.taishinMerchantId = taishinMerchantId;
}
public void setEsunMerchantId(String esunMerchantId) {
this.esunMerchantId = esunMerchantId;
}
public void setGpuseMerchantId(String gpuseMerchantId) {
this.gpuseMerchantId = gpuseMerchantId;
}
}

View File

@ -0,0 +1,85 @@
package com.unibuy.smartdevice.structure;
public class InvoiceItemStructure {
private String itemSeq;
private String itemName;
private int itemCount;
private String itemWord;
private int itemPrice;
private String itemTaxType = "1";
private int itemAmount;
private String itemRemark = "商品備註: 無";
public String getItemSeq() {
return itemSeq;
}
public String getItemName() {
return itemName;
}
public int getItemCount() {
return itemCount;
}
public String getItemWord() {
return itemWord;
}
public int getItemPrice() {
return itemPrice;
}
public String getItemTaxType() {
return itemTaxType;
}
public int getItemAmount() {
return itemAmount;
}
public String getItemRemark() {
return itemRemark;
}
public void setItemSeq(String itemSeq) {
this.itemSeq = itemSeq;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public void setItemCount(int itemCount) {
this.itemCount = itemCount;
}
public void setItemWord(String itemWord) {
this.itemWord = itemWord;
}
public void setItemPrice(int itemPrice) {
this.itemPrice = itemPrice;
}
public void setItemTaxType(String itemTaxType) {
this.itemTaxType = itemTaxType;
}
public void setItemAmount(int itemAmount) {
this.itemAmount = itemAmount;
}
public void setItemRemark(String itemRemark) {
this.itemRemark = itemRemark;
}
public InvoiceItemStructure(String itemSeq, String itemName, int itemCount, String itemWord, int itemPrice, int itemAmount) {
this.itemSeq = itemSeq;
this.itemName = itemName;
this.itemCount = itemCount;
this.itemWord = itemWord;
this.itemPrice = itemPrice;
this.itemAmount = itemAmount;
}
}

View File

@ -0,0 +1,52 @@
package com.unibuy.smartdevice.structure;
public class InvoiceStructure {
private String phone; //電話號碼
private String customerIdentifier; //統一編號
private String carrier; //載具
private String loveCode; //愛心碼
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getCustomerIdentifier() {
return customerIdentifier;
}
public void setCustomerIdentifier(String customerIdentifier) {
this.customerIdentifier = customerIdentifier;
}
public String getCarrier() {
return carrier;
}
public void setCarrier(String carrier) {
this.carrier = carrier;
}
public String getLoveCode() {
return loveCode;
}
public void setLoveCode(String loveCode) {
this.loveCode = loveCode;
}
/*
168001
OMG 關懷社會愛心基金會
*/
public InvoiceStructure(String phone, String customerIdentifier, String carrier, String loveCode) {
this.phone = phone;
this.customerIdentifier = customerIdentifier;
this.carrier = carrier;
this.loveCode = loveCode;
}
}

View File

@ -0,0 +1,30 @@
package com.unibuy.smartdevice.structure;
public class MachineStructure {
private String apiKey = "KahnEwjhfDBHUYS7";
private String machineID;
public MachineStructure(String machineID) {
this.machineID = machineID;
}
// public MachineStructure(String apiKey, String machineID) {
// this.apiKey = apiKey;
// this.machineID = machineID;
// }
public String getApiKey() {
return apiKey;
}
// public void setApiKey(String apiKey) {
// this.apiKey = apiKey;
// }
public String getMachineID() {
return machineID;
}
public void setMachineID(String machineID) {
this.machineID = machineID;
}
}

View File

@ -0,0 +1,90 @@
package com.unibuy.smartdevice.structure;
import org.json.JSONObject;
public class MarketingPlanStructure {
private int field;
private int slot;
private ProductStructure product;
private int count;
private boolean lock;
private JSONObject otherData;
private boolean isMarketingPlan;
public MarketingPlanStructure(int field, int slot, ProductStructure product, int count, JSONObject otherData) {
this.field = field;
this.slot = slot;
this.product = product;
this.count = count;
this.otherData = otherData;
}
@Override
public String toString() {
return "SlotStructure{" +
"field=" + field +
", slot=" + slot +
", product=" + (product != null ? product.toString() : "null") +
", count=" + count +
", lock=" + lock +
", isMarketingPlan=" + isMarketingPlan +
", otherData=" + (otherData != null ? otherData.toString() : "{}") +
'}';
}
public MarketingPlanStructure(int field, int slot, ProductStructure product, int count) {
this(field, slot, product, count, new JSONObject());
}
public int getField() {
return field;
}
public void setField(int field) {
this.field = field;
}
public int getSlot() {
return this.slot;
}
public void setSlot(int slot) {
this.slot = slot;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public boolean isMarketingPlan() {
return isMarketingPlan;
}
public void setMarketingPlan(boolean marketingPlan) {
isMarketingPlan = marketingPlan;
}
public boolean isLock() {
return lock;
}
public void setLock(boolean lock) {
this.lock = lock;
}
public ProductStructure getProduct() {
return this.product;
}
public void setProduct(ProductStructure product) {
this.product = product;
}
public JSONObject getOtherData() {
return otherData;
}
public void setOtherData(JSONObject otherData) {
this.otherData = otherData;
}
}

View File

@ -0,0 +1,57 @@
package com.unibuy.smartdevice.structure;
public class MemberVerificationStructure {
private String productId;
private int productPrice;
private String memberBarCode;
private int verificationType;
public MemberVerificationStructure(String productId, int productPrice, String memberBarCode, int verificationType) {
this.productId = productId;
this.productPrice = productPrice;
this.memberBarCode = memberBarCode;
this.verificationType = verificationType;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public int getProductPrice() {
return productPrice;
}
public void setProductPrice(int productPrice) {
this.productPrice = productPrice;
}
public String getMemberBarCode() {
return memberBarCode;
}
public void setMemberBarCode(String memberBarCode) {
this.memberBarCode = memberBarCode;
}
public int getVerificationType() {
return verificationType;
}
public void setVerificationType(int verificationType) {
this.verificationType = verificationType;
}
@Override
public String toString() {
return "MemberVerificationStructure{" +
"productId='" + productId + '\'' +
", productPrice='" + productPrice + '\'' +
", memberBarCode='" + memberBarCode + '\'' +
", verificationType='" + verificationType + '\'' +
'}';
}
}

View File

@ -0,0 +1,43 @@
package com.unibuy.smartdevice.structure;
import org.json.JSONObject;
public class MemoStructure {
private String field;
private JSONObject data;
private JSONObject otherData;
public MemoStructure(String field, JSONObject data, JSONObject otherData) {
this.field = field;
this.data = data;
this.otherData = otherData;
}
@Override
public String toString() {
return "MemoStructure{" +
"field=" + field +
", data=" + (data != null ? data.toString() : "{}") +
", otherData=" + (otherData != null ? otherData.toString() : "{}") +
'}';
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public JSONObject getData() {
return data;
}
public void setData(JSONObject data) {
this.data = data;
}
public JSONObject getOtherData() {
return otherData;
}
public void setOtherData(JSONObject otherData) {
this.otherData = otherData;
}
}

View File

@ -0,0 +1,59 @@
package com.unibuy.smartdevice.structure;
import java.util.List;
public class PostInvoiceByGreenStructure {
String orderId;
String reportFlowId;
int totalPrice;
InvoiceStructure invoiceData;
List<InvoiceItemStructure> invoiceItem;
public PostInvoiceByGreenStructure(String orderId, String reportFlowId, int totalPrice, InvoiceStructure invoiceData, List<InvoiceItemStructure> invoiceItem) {
this.orderId = orderId;
this.reportFlowId = reportFlowId;
this.totalPrice = totalPrice;
this.invoiceData = invoiceData;
this.invoiceItem = invoiceItem;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getReportFlowId() {
return reportFlowId;
}
public void setReportFlowId(String reportFlowId) {
this.reportFlowId = reportFlowId;
}
public int getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(int totalPrice) {
this.totalPrice = totalPrice;
}
public InvoiceStructure getInvoiceData() {
return invoiceData;
}
public void setInvoiceData(InvoiceStructure invoiceData) {
this.invoiceData = invoiceData;
}
public List<InvoiceItemStructure> getInvoiceItem() {
return invoiceItem;
}
public void setInvoiceItem(List<InvoiceItemStructure> invoiceItem) {
this.invoiceItem = invoiceItem;
}
}

View File

@ -0,0 +1,142 @@
package com.unibuy.smartdevice.structure;
public class ProductStructure {
private String productID;
private String productImg;
private String productName;
private int machinePrice;
private int sellingPrice;
private int memberPrice;
private int slotUpperLimit;
private String marketingPlan;
private String materialCode;
private String productNameEn;
private String productNameJp;
public ProductStructure(String productID, String productImg, String productName, int machinePrice, int sellingPrice, int memberPrice, int slotUpperLimit, String marketingPlan, String materialCode,String productNameEn,String productNameJp) {
this.productID = productID;
this.productImg = productImg;
this.productName = productName;
this.machinePrice = machinePrice;
this.sellingPrice = sellingPrice;
this.memberPrice = memberPrice;
this.slotUpperLimit = slotUpperLimit;
this.marketingPlan = marketingPlan;
this.materialCode = materialCode;
this.productNameEn = productNameEn;
this.productNameJp = productNameJp;
}
public String getProductID() {
return this.productID;
}
public void setProductID(String productID) {
this.productID = productID;
}
public String getProductImg() {
return this.productImg;
}
public void setProductImg(String productImg) {
this.productImg = productImg;
}
public String getProductName() {
return this.productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public int getMachinePrice() {
return this.machinePrice;
}
public void setMachinePrice(int machinePrice) {
this.machinePrice = machinePrice;
}
public int getSellingPrice() {
return sellingPrice;
}
public void setSellingPrice(int sellingPrice) {
this.sellingPrice = sellingPrice;
}
public int getMemberPrice() {
return this.memberPrice;
}
public void setMemberPrice(int memberPrice) {
this.memberPrice = memberPrice;
}
public int getSlotUpperLimit() {
return this.slotUpperLimit;
}
public void setSlotUpperLimit(int slotUpperLimit) {
this.slotUpperLimit = slotUpperLimit;
}
public String getMarketingPlan() {
return this.marketingPlan;
}
public void setMarketingPlan(String marketingPlan) {
this.marketingPlan = marketingPlan;
}
public String getMaterialCode() {
return materialCode;
}
public void setMaterialCode(String materialCode) {
this.materialCode = materialCode;
}
public String getProductNameEn() {
return productNameEn;
}
public void setProductNameEn(String productNameEn) {
this.productNameEn = productNameEn;
}
public String getProductNameJp() {
return productNameJp;
}
public void setProductNameJp(String productNameJp) {
this.productNameJp = productNameJp;
}
public int getRealPrice() {
int machinePrice = getMachinePrice();
int sellingPrice = getSellingPrice();
int memberPrice = getMemberPrice();
int price = machinePrice > 0 ? machinePrice : sellingPrice;
return price;
}
@Override
public String toString() {
return "ProductStructure {" +
"productID='" + productID + '\'' +
", productImg='" + productImg + '\'' +
", productName='" + productName + '\'' +
", machinePrice=" + machinePrice +
", sellingPrice=" + sellingPrice +
", memberPrice=" + memberPrice +
", slotUpperLimit=" + slotUpperLimit +
", marketingPlan='" + marketingPlan + '\'' +
", materialCode='" + materialCode + '\'' +
", productNameEn='" + productNameEn + '\'' +
", productNameJp='" + productNameJp + '\'' +
'}';
}
}

View File

@ -0,0 +1,57 @@
package com.unibuy.smartdevice.structure;
public class ReportAccessCodeStructure {
private String accessCodeId;
private int field;
private int slot;
private String passCode;
private String productId;
public ReportAccessCodeStructure(String accessCodeId, int field, int slot, String passCode, String productId) {
this.accessCodeId = accessCodeId;
this.field = field;
this.slot = slot;
this.passCode = passCode;
this.productId = productId;
}
public String getAccessCodeId() {
return accessCodeId;
}
public void setAccessCodeId(String accessCodeId) {
this.accessCodeId = accessCodeId;
}
public int getField() {
return field;
}
public void setField(int field) {
this.field = field;
}
public int getSlot() {
return slot;
}
public void setSlot(int slot) {
this.slot = slot;
}
public String getPassCode() {
return passCode;
}
public void setPassCode(String passCode) {
this.passCode = passCode;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
}

View File

@ -0,0 +1,127 @@
package com.unibuy.smartdevice.structure;
public class ReportDispatchInfoStructure {
String reportFlowId;
int flowType;
String productId;
int slot;
int totalPrice;
String orderId;
int remaining;
String mamberBarCcde;
String VoucherId;
int dispatchStatusType;
int ownPrice;
int usePoints;
public ReportDispatchInfoStructure(String reportFlowId, int flowType, String productId, int slot, int totalPrice, String orderId, int remaining, String mamberBarCcde, String voucherId, int dispatchStatusType, int ownPrice, int usePoints) {
this.reportFlowId = reportFlowId;
this.flowType = flowType;
this.productId = productId;
this.slot = slot;
this.totalPrice = totalPrice;
this.orderId = orderId;
this.remaining = remaining;
this.mamberBarCcde = mamberBarCcde;
VoucherId = voucherId;
this.dispatchStatusType = dispatchStatusType;
this.ownPrice = ownPrice;
this.usePoints = usePoints;
}
public String getReportFlowId() {
return reportFlowId;
}
public void setReportFlowId(String reportFlowId) {
this.reportFlowId = reportFlowId;
}
public int getFlowType() {
return flowType;
}
public void setFlowType(int flowType) {
this.flowType = flowType;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public int getSlot() {
return slot;
}
public void setSlot(int slot) {
this.slot = slot;
}
public int getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(int totalPrice) {
this.totalPrice = totalPrice;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public int getRemaining() {
return remaining;
}
public void setRemaining(int remaining) {
this.remaining = remaining;
}
public String getMamberBarCcde() {
return mamberBarCcde;
}
public void setMamberBarCcde(String mamberBarCcde) {
this.mamberBarCcde = mamberBarCcde;
}
public String getVoucherId() {
return VoucherId;
}
public void setVoucherId(String voucherId) {
VoucherId = voucherId;
}
public int getDispatchStatusType() {
return dispatchStatusType;
}
public void setDispatchStatusType(int dispatchStatusType) {
this.dispatchStatusType = dispatchStatusType;
}
public int getOwnPrice() {
return ownPrice;
}
public void setOwnPrice(int ownPrice) {
this.ownPrice = ownPrice;
}
public int getUsePoints() {
return usePoints;
}
public void setUsePoints(int usePoints) {
this.usePoints = usePoints;
}
}

View File

@ -0,0 +1,156 @@
package com.unibuy.smartdevice.structure;
import org.json.JSONArray;
public class ReportFlowInfoStructure {
String orderId;
int flowType;
String flowSendInfo;
String flowRequestInfo;
String productId;
int totalPrice;
String invoiceInfo;
String flowBarCode;
int flowStatusType;
int giveChange;
int usePoints;
String reportFlowId;
JSONArray shoppingCartInfoByJsonArray;
public ReportFlowInfoStructure(String orderId, int flowType, String flowSendInfo, String flowRequestInfo, String productId, int totalPrice, String invoiceInfo, String flowBarCode, int flowStatusType, int giveChange, int usePoints, JSONArray shoppingCartInfoByJsonArray) {
this.orderId = orderId;
this.flowType = flowType;
this.flowSendInfo = flowSendInfo;
this.flowRequestInfo = flowRequestInfo;
this.productId = productId;
this.totalPrice = totalPrice;
this.invoiceInfo = invoiceInfo;
this.flowBarCode = flowBarCode;
this.flowStatusType = flowStatusType;
this.giveChange = giveChange;
this.usePoints = usePoints;
this.shoppingCartInfoByJsonArray = shoppingCartInfoByJsonArray;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public int getFlowType() {
return flowType;
}
public void setFlowType(int flowType) {
this.flowType = flowType;
}
public String getFlowSendInfo() {
return flowSendInfo;
}
public void setFlowSendInfo(String flowSendInfo) {
this.flowSendInfo = flowSendInfo;
}
public String getFlowRequestInfo() {
return flowRequestInfo;
}
public void setFlowRequestInfo(String flowRequestInfo) {
this.flowRequestInfo = flowRequestInfo;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public int getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(int totalPrice) {
this.totalPrice = totalPrice;
}
public String getInvoiceInfo() {
return invoiceInfo;
}
public void setInvoiceInfo(String invoiceInfo) {
this.invoiceInfo = invoiceInfo;
}
public String getFlowBarCode() {
return flowBarCode;
}
public void setFlowBarCode(String flowBarCode) {
this.flowBarCode = flowBarCode;
}
public int getFlowStatusType() {
return flowStatusType;
}
public void setFlowStatusType(int flowStatusType) {
this.flowStatusType = flowStatusType;
}
public int getGiveChange() {
return giveChange;
}
public void setGiveChange(int giveChange) {
this.giveChange = giveChange;
}
public int getUsePoints() {
return usePoints;
}
public void setUsePoints(int usePoints) {
this.usePoints = usePoints;
}
public JSONArray getShoppingCartInfoByJsonArray() {
return shoppingCartInfoByJsonArray;
}
public void setShoppingCartInfoByJsonArray(JSONArray shoppingCartInfoByJsonArray) {
this.shoppingCartInfoByJsonArray = shoppingCartInfoByJsonArray;
}
public String getReportFlowId() {
return reportFlowId;
}
public void setReportFlowId(String reportFlowId) {
this.reportFlowId = reportFlowId;
}
@Override
public String toString() {
return "ReportFlowInfoStructure{" +
"orderId='" + orderId + '\'' +
", flowType=" + flowType +
", flowSendInfo='" + flowSendInfo + '\'' +
", flowRequestInfo='" + flowRequestInfo + '\'' +
", productId='" + productId + '\'' +
", totalPrice=" + totalPrice +
", invoiceInfo='" + invoiceInfo + '\'' +
", flowBarCode='" + flowBarCode + '\'' +
", flowStatusType=" + flowStatusType +
", giveChange=" + giveChange +
", usePoints=" + usePoints +
", shoppingCartInfoByJsonArray=" + shoppingCartInfoByJsonArray +
'}';
}
}

View File

@ -0,0 +1,114 @@
package com.unibuy.smartdevice.structure;
/*
String res1 = jsonArray.getJSONObject(0).getString("res1"); // put id
String res2 = jsonArray.getJSONObject(0).getString("res2"); //mode
String res3 = jsonArray.getJSONObject(0).getString("res3"); //出貨商品代碼
String res4 = jsonArray.getJSONObject(0).getString("res4"); //折扣金額
String res5 = jsonArray.getJSONObject(0).getString("res5"); //折扣折數
*/
public class ReportFreeGiftCodeStructure {
private String freeGiftId;
private int mode;
private String productId;
private int discountAmount;
private float discountPercentage;
private String passCode;
private String reportFlowId;
private int field;
private int slot;
private int money;
public ReportFreeGiftCodeStructure(String freeGiftCodeId, int mode, String productId, int discountAmount, float discountPercentage, String passCode) {
this.freeGiftId = freeGiftCodeId;
this.mode = mode;
this.productId = productId;
this.discountAmount = discountAmount;
this.discountPercentage = discountPercentage;
this.passCode = passCode;
this.reportFlowId = "";
this.field = 0;
this.slot = 0;
this.money = 0;
}
public String getFreeGiftId() {
return freeGiftId;
}
public void setFreeGiftId(String freeGiftId) {
this.freeGiftId = freeGiftId;
}
public int getMode() {
return mode;
}
public void setMode(int mode) {
this.mode = mode;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public int getDiscountAmount() {
return discountAmount;
}
public void setDiscountAmount(int discountAmount) {
this.discountAmount = discountAmount;
}
public float getDiscountPercentage() {
return discountPercentage;
}
public void setDiscountPercentage(float discountPercentage) {
this.discountPercentage = discountPercentage;
}
public String getPassCode() {
return passCode;
}
public void setPassCode(String passCode) {
this.passCode = passCode;
}
public String getReportFlowId() {
return reportFlowId;
}
public void setReportFlowId(String reportFlowId) {
this.reportFlowId = reportFlowId;
}
public int getField() {
return field;
}
public void setField(int field) {
this.field = field;
}
public int getSlot() {
return slot;
}
public void setSlot(int slot) {
this.slot = slot;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}

View File

@ -0,0 +1,90 @@
package com.unibuy.smartdevice.structure;
public class ReportInvoiceInfoStructure {
String reportFlowId;
String rtnCode;
String rtnMsg;
String invoiceNo;
String invoiceDate;
String randomNumber;
String loveCode;
public ReportInvoiceInfoStructure(String reportFlowId, String rtnCode, String rtnMsg, String invoiceNo, String invoiceDate, String randomNumber, String loveCode) {
this.reportFlowId = reportFlowId;
this.rtnCode = rtnCode;
this.rtnMsg = rtnMsg;
this.invoiceNo = invoiceNo;
this.invoiceDate = invoiceDate;
this.randomNumber = randomNumber;
this.loveCode = loveCode;
}
public String getReportFlowId() {
return reportFlowId;
}
public void setReportFlowId(String reportFlowId) {
this.reportFlowId = reportFlowId;
}
public String getRtnCode() {
return rtnCode;
}
public void setRtnCode(String rtnCode) {
this.rtnCode = rtnCode;
}
public String getRtnMsg() {
return rtnMsg;
}
public void setRtnMsg(String rtnMsg) {
this.rtnMsg = rtnMsg;
}
public String getInvoiceNo() {
return invoiceNo;
}
public void setInvoiceNo(String invoiceNo) {
this.invoiceNo = invoiceNo;
}
public String getInvoiceDate() {
return invoiceDate;
}
public void setInvoiceDate(String invoiceDate) {
this.invoiceDate = invoiceDate;
}
public String getRandomNumber() {
return randomNumber;
}
public void setRandomNumber(String randomNumber) {
this.randomNumber = randomNumber;
}
public String getLoveCode() {
return loveCode;
}
public void setLoveCode(String loveCode) {
this.loveCode = loveCode;
}
@Override
public String toString() {
return "ReportInvoiceInfoStructure{" +
"reportFlowId='" + reportFlowId + '\'' +
", rtnCode='" + rtnCode + '\'' +
", rtnMsg='" + rtnMsg + '\'' +
", invoiceNo='" + invoiceNo + '\'' +
", invoiceDate='" + invoiceDate + '\'' +
", randomNumber='" + randomNumber + '\'' +
", loveCode='" + loveCode + '\'' +
'}';
}
}

View File

@ -0,0 +1,47 @@
package com.unibuy.smartdevice.structure;
public class ReportSlotListStructure {
private String machinekey;
private String machine;
private String account;
private String vmctype;
public ReportSlotListStructure(String machinekey, String machine, String account, String vmctype) {
this.machinekey = machinekey;
this.machine = machine;
this.account = account;
this.vmctype = vmctype;
}
public String getMachinekey() {
return machinekey;
}
public void setMachinekey(String machinekey) {
this.machinekey = machinekey;
}
public String getMachine() {
return machine;
}
public void setMachine(String machine) {
this.machine = machine;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getVmctype() {
return vmctype;
}
public void setVmctype(String vmctype) {
this.vmctype = vmctype;
}
}

View File

@ -0,0 +1,54 @@
package com.unibuy.smartdevice.structure;
import android.util.Log;
public class SettingStructure {
private String settingId;
private String[] data;
public SettingStructure(String settingId, String[] data) {
this.settingId = settingId;
this.data = data;
}
public String getSettingId() {
return settingId;
}
public void setSettingId(String settingId) {
this.settingId = settingId;
}
public int getDataCount() {
return data.length;
}
public String getData(int index) {
if (index < data.length && data[index] != null) {
return data[index];
} else {
return "";
}
}
public void setData(int index, String data) {
this.data[index] = data;
}
@Override
public String toString() {
return "SettingStructure{" +
"settingId='" + settingId + '\'' +
", data1(0)='" + getData(0) + '\'' +
", data2(1)='" + getData(1) + '\'' +
", data3(2)='" + getData(2) + '\'' +
", data4(3)='" + getData(3) + '\'' +
", data5(4)='" + getData(4) + '\'' +
", data6(5)='" + getData(5) + '\'' +
", data7(6)='" + getData(6) + '\'' +
", data8(7)='" + getData(7) + '\'' +
", data9(8)='" + getData(8) + '\'' +
", data10(9)='" + getData(9) + '\'' +
'}';
}
}

Some files were not shown because too many files have changed in this diff Show More