diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..61ab3f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,85 @@ +# Built application files +*.apk +*.aar +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ +# Uncomment the following line in case you need and you don't have the release build type files in your app +# release/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/ +# Android Studio 3 in .gitignore file. +.idea/caches +.idea/modules.xml +# Comment next line if keeping position of elements in Navigation Editor is relevant for you +.idea/navEditor.xml + +# Keystore files +# Uncomment the following lines if you do not want to check your keystore files in. +#*.jks +#*.keystore + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.cxx/ + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md + +# Version control +vcs.xml + +# lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ +# lint/reports/ + +/app/key +output-metadata.json +# Android Profiling +*.hprof diff --git a/README.md b/README.md index e69de29..718eda6 100644 --- a/README.md +++ b/README.md @@ -0,0 +1 @@ +# 摆药机 \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..f5079c5 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,85 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-kapt' + + +android { + compileSdkVersion versions.compileSdk + buildToolsVersion versions.buildTools + + defaultConfig { + applicationId apps.applicationId + minSdkVersion versions.minSdk + targetSdkVersion versions.targetSdk + versionCode versions.versionCode + versionName versions.versionName + + manifestPlaceholders = [ + APP_NAME: apps.applicationName, + APP_ID : apps.applicationId, + ] + buildConfigField("String", "APP_Name", "\"" + apps.applicationName + "\"") + + flavorDimensions "versioncode" + } + buildTypes { + debug { + minifyEnabled false + signingConfig signingConfigs.debug + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + release { + minifyEnabled false + signingConfig signingConfigs.debug + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + applicationVariants.all { variant -> + variant.outputs.all { output -> + if ("debug" != variant.buildType.name) { + def now = new Date() + def path = "../../../../../apks/${variant.buildType.name}/v${defaultConfig.versionName}_" + now.format("yyyy.MM.dd_HH") + outputFileName = path + "/${applicationId}.apk" + } + } + } + signingConfigs { + debug { + keyAlias 'xuqm' + keyPassword 'xuqinmin1022' + storeFile file('key') + storePassword 'xuqinmin1022' + } + releaseConfig {} + } + + sourceSets { + main { + jniLibs.srcDirs = ['libs'] + } + } + androidExtensions { + experimental = true + } + namespace 'com.bjca.hp.acupuncture' +} + +dependencies { + implementation fileTree(dir: "libs", include: ["*.jar","*.aar"]) + implementation project(path: ':core') + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.appcompat:appcompat:1.3.0' + implementation 'com.google.android.material:material:1.3.0' + + implementation 'tp.xmaihh:serialport:2.1' + + implementation 'com.rabbitmq:amqp-client:5.15.0' + + +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..9cbf2ae --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/fonts/DIN-Alternate-Bold.ttf b/app/src/main/assets/fonts/DIN-Alternate-Bold.ttf new file mode 100644 index 0000000..07e127e Binary files /dev/null and b/app/src/main/assets/fonts/DIN-Alternate-Bold.ttf differ diff --git a/app/src/main/assets/fonts/SourceHanSansCN-Bold.ttf b/app/src/main/assets/fonts/SourceHanSansCN-Bold.ttf new file mode 100644 index 0000000..393a93a Binary files /dev/null and b/app/src/main/assets/fonts/SourceHanSansCN-Bold.ttf differ diff --git a/app/src/main/assets/fonts/SourceHanSansCN-Medium.ttf b/app/src/main/assets/fonts/SourceHanSansCN-Medium.ttf new file mode 100644 index 0000000..253ade5 Binary files /dev/null and b/app/src/main/assets/fonts/SourceHanSansCN-Medium.ttf differ diff --git a/app/src/main/assets/fonts/SourceHanSansCN-Normal.otf b/app/src/main/assets/fonts/SourceHanSansCN-Normal.otf new file mode 100644 index 0000000..091f56d Binary files /dev/null and b/app/src/main/assets/fonts/SourceHanSansCN-Normal.otf differ diff --git a/app/src/main/assets/fonts/SourceHanSansCN-Normal.ttf b/app/src/main/assets/fonts/SourceHanSansCN-Normal.ttf new file mode 100644 index 0000000..8026959 Binary files /dev/null and b/app/src/main/assets/fonts/SourceHanSansCN-Normal.ttf differ diff --git a/app/src/main/assets/fonts/SourceHanSansCN-Regular.ttf b/app/src/main/assets/fonts/SourceHanSansCN-Regular.ttf new file mode 100644 index 0000000..11431be Binary files /dev/null and b/app/src/main/assets/fonts/SourceHanSansCN-Regular.ttf differ diff --git a/app/src/main/java/com/bjca/hp/acupuncture/MyApplication.java b/app/src/main/java/com/bjca/hp/acupuncture/MyApplication.java new file mode 100644 index 0000000..2455409 --- /dev/null +++ b/app/src/main/java/com/bjca/hp/acupuncture/MyApplication.java @@ -0,0 +1,33 @@ +package com.bjca.hp.acupuncture; + +import com.xuqm.base.App; +import com.xuqm.base.di.component.AppComponent; +import com.xuqm.base.di.manager.HttpManager; +import com.bjca.hp.acupuncture.common.CrashHandler; +import com.bjca.hp.acupuncture.repository.HeaderInterceptor; + +/** + * @author xuqm + */ +public class MyApplication extends App { + + public static String baseUrl = "http://10.10.203.120:31734"; + public static AppComponent appComponent1; + public static AppComponent appComponent2; + + @Override + public void onCreate() { + super.onCreate(); + appComponent = HttpManager.getAppComponent(baseUrl, new HeaderInterceptor(getApplicationContext())); + appComponent1 = HttpManager.getAppComponent("http://10.10.203.120:35662", new HeaderInterceptor(getApplicationContext())); + appComponent2 = HttpManager.getAppComponent("http://10.10.203.120:31669", new HeaderInterceptor(getApplicationContext())); + + CrashHandler.getInstance().init(this); + + } + + @Override + public boolean showLog() { + return super.showLog(); + } +} diff --git a/app/src/main/java/com/bjca/hp/acupuncture/common/CrashHandler.java b/app/src/main/java/com/bjca/hp/acupuncture/common/CrashHandler.java new file mode 100644 index 0000000..c2bfcc8 --- /dev/null +++ b/app/src/main/java/com/bjca/hp/acupuncture/common/CrashHandler.java @@ -0,0 +1,166 @@ +package com.bjca.hp.acupuncture.common; + +import android.content.Context; +import android.os.Environment; +import android.os.SystemClock; +import android.util.Log; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +/************************************************************************************************* + *
+ * @包路径: cn.org.bjca.wcert.ywq.utils.crash
+ * @版权所有: 北京数字认证股份有限公司 (C) 2017
+ *
+ * @类描述:
+ * @版本: V1.5.1
+ * @作者 daizhenhong
+ * @创建时间 2017/12/13 下午4:22
+ *
+ * @修改记录:
+-----------------------------------------------------------------------------------------------
+----------- 时间      |   修改人    |     修改的方法       |         修改描述   ---------------
+-----------------------------------------------------------------------------------------------
+
+ ************************************************************************************************/ +public class CrashHandler implements Thread.UncaughtExceptionHandler { + + + private static String TAG = "CrashHandler"; + // 系统默认的UncaughtException处理类 + private Thread.UncaughtExceptionHandler mDefaultHandler; + // 用于格式化日期,作为日志文件名的一部分 + private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + private static CrashHandler mCrashHandler; + private Context mContext; + + + private CrashHandler() { + + } + + public static CrashHandler getInstance() { + if (mCrashHandler == null) { + synchronized (CrashHandler.class) { + mCrashHandler = new CrashHandler(); + } + } + return mCrashHandler; + } + + public void init(Context context) { + mContext = context; + mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); + Thread.setDefaultUncaughtExceptionHandler(this); + } + + @Override + public void uncaughtException(Thread thread, Throwable throwable) { + if (!handleException(throwable) && mDefaultHandler != null) { + // 如果用户没有处理则让系统默认的异常处理器来处理 + mDefaultHandler.uncaughtException(thread, throwable); + } else { + SystemClock.sleep(2000); + // 退出程序 + android.os.Process.killProcess(android.os.Process.myPid()); + System.exit(1); + } + } + + + private boolean handleException(Throwable ex) { + if (ex == null) { + return false; + } + try { + saveCrashInfoFile(ex); + SystemClock.sleep(2000); + } catch (Exception e) { + e.printStackTrace(); + } + + return true; + } + + private String saveCrashInfoFile(Throwable ex) { + StringBuffer sb = new StringBuffer(); + + if (hasSdcard()) + try { + SimpleDateFormat sDateFormat = new SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss", Locale.CHINA); + String date = sDateFormat.format(new Date()); + sb.append("\r\n" + date + "\n"); + + Writer writer = new StringWriter(); + PrintWriter printWriter = new PrintWriter(writer); + ex.printStackTrace(printWriter); + Throwable cause = ex.getCause(); + while (cause != null) { + cause.printStackTrace(printWriter); + cause = cause.getCause(); + } + printWriter.flush(); + printWriter.close(); + String result = writer.toString(); + sb.append(result); + + String fileName = writeFile(sb.toString()); + return fileName; + } catch (Exception e) { + Log.e(TAG, "an error occured while writing file...", e); + sb.append("an error occured while writing file...\r\n"); + writeFile(sb.toString()); + } + return null; + } + + private String writeFile(String text) { + Log.e("writeFile", text); + String time = formatter.format(new Date()); + String fileName = "crash-demo-" + time + ".log"; + + String path = getGlobalpath(); + + File dir = new File(path); + if (!dir.exists()) { + dir.mkdir(); + } + FileOutputStream fos = null; + try { + fos = new FileOutputStream(path + fileName, true); + fos.write(text.getBytes()); + fos.flush(); + fos.close(); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return fileName; + } + + + public String getGlobalpath() { + return Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + "crash" + File.separator; + } + + + public boolean hasSdcard(){ + return Environment.getExternalStorageState() + .equals(Environment.MEDIA_MOUNTED); + } +} + diff --git a/app/src/main/java/com/bjca/hp/acupuncture/common/RabbitMQClient.java b/app/src/main/java/com/bjca/hp/acupuncture/common/RabbitMQClient.java new file mode 100644 index 0000000..ce596d2 --- /dev/null +++ b/app/src/main/java/com/bjca/hp/acupuncture/common/RabbitMQClient.java @@ -0,0 +1,248 @@ +package com.bjca.hp.acupuncture.common; + +import android.text.TextUtils; +import android.util.Log; + +import com.rabbitmq.client.AMQP; +import com.rabbitmq.client.AlreadyClosedException; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.DefaultConsumer; +import com.rabbitmq.client.Envelope; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeoutException; + +/*************************************************************************** + *

+ * @文件名称: RabbitMQClient
+ * @包 路   径:  com.bjca.hp.acupuncture.common
+ * @版权所有:北京数字医信责任有限公司 (C) 2022
+ *
+ * @类描述:
+ * @版本: V1.0
+ * @创建人: xuqm
+ * @创建时间:2022/6/15 下午 02:19
+ * @修改记录:
+ */
+public class RabbitMQClient {
+    private final String TAG = "RabbitMQ";
+    private final String FLAG_SEND = "send";
+    private final String FLAG_RECEIVE = "receive";
+
+    private final ConnectionFactory factory;
+    private Connection connection;
+    private Map channelMap = new HashMap<>();
+
+    public static final String EXCHANGETYPE_FANOUT = "fanout";   //不用匹配路由,发送给所有绑定转换器的队列
+    public static final String EXCHANGETYPE_DIRECT = "direct";  //匹配路由一致,才发送给绑定转换器队列
+    public static final String EXCHANGETYPE_TOPIC = "topic";  // 通配符* 和 # 匹配路由一致,才发送给绑定转换器队列
+
+
+    public RabbitMQClient(String hostIp, int port, String username, String password) {
+        factory = new ConnectionFactory();
+        factory.setUsername(username);
+        factory.setPassword(password);
+        factory.setHost(hostIp);
+        factory.setPort(port);
+        factory.setVirtualHost("/");//类似数据库的意思
+        factory.setConnectionTimeout(15 * 1000);         //连接时间设置为10秒
+        factory.setAutomaticRecoveryEnabled(true);   //恢复连接,通道
+        factory.setTopologyRecoveryEnabled(true);    //恢复通道中 转换器,队列,绑定关系等
+        factory.setNetworkRecoveryInterval(5 * 1000);    //恢复连接间隔,默认5秒
+    }
+
+
+    /**
+     * @param message   需要发送的消息
+     * @param queueName 管道名称
+     * @date 创建时间:2020/9/8 0008
+     * @auther gaoxiaoxiong
+     * @Descriptiion
+     **/
+    public void sendQueueMessage(String message, String queueName) throws IOException, TimeoutException, AlreadyClosedException {
+        if (connection == null || !connection.isOpen()) {
+            connection = factory.newConnection();
+        }
+        if (!channelMap.containsKey(FLAG_SEND + queueName)) {
+            Channel channel = connection.createChannel();
+            channel.queueDeclare(queueName, false, false, false, null);
+            channelMap.put(FLAG_SEND + queueName, channel);
+        }
+        //空名字的交换机,需要设置routingKey,此时会将routingKey 作为 队列名使用
+        channelMap.get(FLAG_SEND + queueName).basicPublish("", queueName, null, message.getBytes());
+    }
+
+
+    /**
+     * @param exchangeName 交换机名称
+     * @param message      需要发送的消息
+     * @param queueName    队列名称
+     * @param routingKey   路由规则
+     * @date 创建时间:2020/9/8 0008
+     * @auther gaoxiaoxiong
+     * @Descriptiion 发送 exchangeType direct 类型的信息
+     **/
+    public void sendDirectTypeMessage(String exchangeName, String message, String queueName, String routingKey) throws IOException, TimeoutException, AlreadyClosedException {
+        if (connection == null || !connection.isOpen()) {
+            connection = factory.newConnection();
+        }
+        if (!channelMap.containsKey(FLAG_SEND + exchangeName + EXCHANGETYPE_DIRECT + queueName)) {
+            Channel channel = connection.createChannel();
+            channel.queueDeclare(queueName, false, false, false, null);
+            channel.exchangeDeclare(exchangeName, EXCHANGETYPE_DIRECT);
+            channelMap.put(FLAG_SEND + exchangeName + EXCHANGETYPE_DIRECT + queueName, channel);
+        }
+        channelMap.get(FLAG_SEND + exchangeName + EXCHANGETYPE_DIRECT + queueName).basicPublish(exchangeName, routingKey, null, message.getBytes());
+    }
+
+    /**
+     * @param exchangeName 交换机名称
+     * @param queueName    队列名称
+     * @param message      发送的消息
+     * @date 创建时间:2020/9/8 0008
+     * @auther gaoxiaoxiong
+     * @Descriptiion 发送 exchangeType fanout 类型的信息
+     **/
+    public void sendFanoutTypeMessage(String exchangeName, String queueName, String message) throws IOException, TimeoutException, AlreadyClosedException {
+        if (connection == null || !connection.isOpen()) {
+            connection = factory.newConnection();
+        }
+        if (!channelMap.containsKey(FLAG_SEND + exchangeName + EXCHANGETYPE_FANOUT + queueName)) {
+            Channel channel = connection.createChannel();
+            channel.queueDeclare(queueName, false, false, false, null);
+            channel.exchangeDeclare(exchangeName, EXCHANGETYPE_FANOUT);
+            channelMap.put(FLAG_SEND + exchangeName + EXCHANGETYPE_FANOUT + queueName, channel);
+        }
+        channelMap.get(FLAG_SEND + exchangeName + EXCHANGETYPE_FANOUT + queueName).basicPublish(exchangeName, "", null, message.getBytes());
+    }
+
+    /**
+     * @param exchangeName 交换机名称
+     * @param exchangeType 模式
+     * @param queueName    队列名称
+     * @param message      需要发送的消息
+     * @param routingKey   路由规则
+     * @date 创建时间:2020/9/8 0008
+     * @auther gaoxiaoxiong
+     * @Descriptiion
+     **/
+    public void sendExchangeNameQueueMessage(String exchangeName, String exchangeType, String message, String queueName, String routingKey) throws IOException, TimeoutException, AlreadyClosedException {
+        if (connection == null || !connection.isOpen()) {
+            connection = factory.newConnection();
+        }
+        if (!channelMap.containsKey(FLAG_SEND + exchangeName + exchangeType + queueName)) {
+            Channel channel = connection.createChannel();
+            channel.queueDeclare(queueName, false, false, false, null);
+            channel.exchangeDeclare(exchangeName, exchangeType);
+            channelMap.put(FLAG_SEND + exchangeName + exchangeType + queueName, channel);
+        }
+        if (exchangeType.equals(EXCHANGETYPE_FANOUT)) {
+            channelMap.get(FLAG_SEND + exchangeName + exchangeType + queueName).basicPublish(exchangeName, "", null, message.getBytes());
+        } else if (exchangeType.equals(EXCHANGETYPE_DIRECT)) {
+            channelMap.get(FLAG_SEND + exchangeName + exchangeType + queueName).basicPublish(exchangeName, routingKey, null, message.getBytes());
+        } else if (exchangeType.equals(EXCHANGETYPE_TOPIC)) {
+            channelMap.get(FLAG_SEND + exchangeName + exchangeType + queueName).basicPublish(exchangeName, routingKey, null, message.getBytes());
+        }
+    }
+
+
+    /**
+     * @param queueName 队列名称
+     * @date 创建时间:2020/9/8 0008
+     * @auther gaoxiaoxiong
+     * @Descriptiion
+     **/
+    public void receiveQueueMessage(final String queueName, final ResponseListener listener)
+            throws IOException, TimeoutException, AlreadyClosedException {
+        receiveQueueRoutingKeyMessage(queueName, "", "", "", listener);
+    }
+
+
+    /**
+     * @param queueName    队列名称
+     * @param routingKey   路由规则
+     * @param exchangeName 交换机名称
+     * @param exchangeType 交换机类型
+     * @date 创建时间:2020/9/8 0008
+     * @auther gaoxiaoxiong
+     * @Descriptiion
+     **/
+    public void receiveQueueRoutingKeyMessage(String queueName, final String routingKey, String exchangeName, String exchangeType, final ResponseListener listener)
+            throws IOException, TimeoutException, AlreadyClosedException {
+
+        if (exchangeType.equals(EXCHANGETYPE_DIRECT) || exchangeType.equals(EXCHANGETYPE_TOPIC)) {
+            if (TextUtils.isEmpty(routingKey)) {
+                throw new NullPointerException("路由规则不能为空");
+            }
+        }
+
+        if (!TextUtils.isEmpty(routingKey)) {
+            if (TextUtils.isEmpty(exchangeName)) {
+                throw new NullPointerException("交换机名称不能为空");
+            }
+        }
+
+        if (!channelMap.containsKey(FLAG_RECEIVE + routingKey + queueName)) {
+            if (connection == null || !connection.isOpen()) {
+                connection = factory.newConnection();
+            }
+
+            final Channel channel = connection.createChannel();
+            channel.queueDeclare(queueName, true, false, false, null);
+            //绑定转换器,使用路由筛选消息
+            if (!TextUtils.isEmpty(routingKey)) {
+                channel.exchangeDeclare(exchangeName, exchangeType);
+                channel.queueBind(queueName, exchangeName, routingKey);  //设置绑定
+            }
+            //监听队列
+            channel.basicConsume(queueName, false, new DefaultConsumer(channel) {
+                @Override
+                public void handleDelivery(String consumerTag, Envelope envelope,
+                                           AMQP.BasicProperties properties, byte[] body)
+                        throws IOException {
+                    String message = new String(body, "UTF-8");
+                    if (listener != null) {
+                        listener.receive(message);
+                    }
+                    channel.basicAck(envelope.getDeliveryTag(), false);  //消息应答
+                }
+            });
+            channelMap.put(FLAG_RECEIVE + routingKey + queueName, channel);
+            Log.e(TAG,"已经连接上了,队列名称:" + queueName);
+        }
+    }
+
+
+    /**
+     * 关闭所有资源
+     */
+    public void close() {
+        for (Channel next : channelMap.values()) {
+            if (next != null && next.isOpen()) {
+                try {
+                    next.close();
+                } catch (IOException | TimeoutException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        channelMap.clear();
+        if (connection != null && connection.isOpen()) {
+            try {
+                connection.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+
+    public interface ResponseListener {
+        void receive(String message);
+    }
+}
+
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/common/RabbitMQUtil.java b/app/src/main/java/com/bjca/hp/acupuncture/common/RabbitMQUtil.java
new file mode 100644
index 0000000..ec689f0
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/common/RabbitMQUtil.java
@@ -0,0 +1,239 @@
+package com.bjca.hp.acupuncture.common;
+
+import android.os.SystemClock;
+import android.text.TextUtils;
+
+import com.rabbitmq.client.AlreadyClosedException;
+
+import java.io.IOException;
+import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeoutException;
+
+/***************************************************************************
+ * 

+ * @文件名称: RabbitMQUtil
+ * @包 路   径:  com.bjca.hp.acupuncture.common
+ * @版权所有:北京数字医信责任有限公司 (C) 2022
+ *
+ * @类描述:
+ * @版本: V1.0
+ * @创建人: xuqm
+ * @创建时间:2022/6/15 下午 02:22
+ * @修改记录:
+ */
+public class RabbitMQUtil {
+    private boolean isRunning = true;
+    private RabbitMQClient rabbitMQ;
+    private ExecutorService executor;
+
+
+    public RabbitMQUtil(String hostIp, int port, String username, String password) {
+        rabbitMQ = new RabbitMQClient(hostIp, port, username, password);
+        executor = Executors.newSingleThreadExecutor();  //根据项目需要设置常用线程个数
+    }
+
+    /**
+     * @param message   发送的消息
+     * @param queueName 队列名称
+     * @date 创建时间:2020/9/8 0008
+     * @auther gaoxiaoxiong
+     * @Descriptiion
+     **/
+    public void sendMessage(final String message, final String queueName, final SendMessageListener sendMessageListener,final ErrorMessageListener errorMessageListener) {
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    rabbitMQ.sendQueueMessage(message, queueName);
+                    if (sendMessageListener != null) sendMessageListener.sendMessage(true);
+                } catch (IOException | TimeoutException | AlreadyClosedException e) {
+                    e.printStackTrace();
+                    if (errorMessageListener!=null){
+                        errorMessageListener.errorMessage(e);
+                    }
+                    if (sendMessageListener != null) sendMessageListener.sendMessage(false);
+                }
+            }
+        });
+    }
+
+    /**
+     * @param message      发送的消息
+     * @param exchangeName 交换机名称
+     * @param queueName    队列名称
+     * @date 创建时间:2020/9/8 0008
+     * @auther gaoxiaoxiong
+     * @Descriptiion
+     **/
+    public void sendMessage(final String message, final String exchangeName, final String exchangeType, final String queueName, final String routingKey, final SendMessageListener sendMessageListener,final ErrorMessageListener errorMessageListener) {
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    rabbitMQ.sendExchangeNameQueueMessage(exchangeName, exchangeType, message, queueName, routingKey);
+                    if (sendMessageListener != null) sendMessageListener.sendMessage(true);
+                } catch (IOException | TimeoutException | AlreadyClosedException e) {
+                    e.printStackTrace();
+                    if (errorMessageListener!=null){
+                        errorMessageListener.errorMessage(e);
+                    }
+                    if (sendMessageListener != null) sendMessageListener.sendMessage(false);
+                }
+            }
+        });
+    }
+
+    /**
+     * @param exchangeName 交换机名称
+     * @param queueName    队列名称
+     * @param message      需要发送的消息
+     * @date 创建时间:2020/9/8 0008
+     * @auther gaoxiaoxiong
+     * @Descriptiion
+     **/
+    public void sendFanoutTypeMessage(final String exchangeName, final String message, final String queueName, final SendMessageListener sendMessageListener,final ErrorMessageListener errorMessageListener) {
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    rabbitMQ.sendFanoutTypeMessage(exchangeName, queueName, message);
+                    if (sendMessageListener != null) sendMessageListener.sendMessage(true);
+                } catch (IOException | TimeoutException | AlreadyClosedException e) {
+                    e.printStackTrace();
+                    if (errorMessageListener!=null){
+                        errorMessageListener.errorMessage(e);
+                    }
+                    if (sendMessageListener != null) sendMessageListener.sendMessage(false);
+                }
+            }
+        });
+    }
+
+    /**
+     * @param exchangeName 交换机名称
+     * @param message      需要发送的消息
+     * @param queueName    队列名称
+     * @param routingKey   路由规则
+     * @date 创建时间:2020/9/8 0008
+     * @auther gaoxiaoxiong
+     * @Descriptiion 发送 exchangeType direct 类型的信息
+     **/
+    public void sendDirectTypeMessage(final String exchangeName, final String queueName, final String message, final String routingKey, final SendMessageListener sendMessageListener,final ErrorMessageListener errorMessageListener) {
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    rabbitMQ.sendDirectTypeMessage(exchangeName, queueName, message, routingKey);
+                    if (sendMessageListener != null) sendMessageListener.sendMessage(true);
+                } catch (IOException | TimeoutException | AlreadyClosedException e) {
+                    e.printStackTrace();
+                    if (errorMessageListener!=null){
+                        errorMessageListener.errorMessage(e);
+                    }
+                    if (sendMessageListener != null) sendMessageListener.sendMessage(false);
+                }
+            }
+        });
+    }
+
+    /**
+     * @param queueName 队列名称
+     * @date 创建时间:2020/9/8 0008
+     * @auther gaoxiaoxiong
+     * @Descriptiion
+     **/
+    public void receiveQueueMessage(String queueName, final ReceiveMessageListener listener,final ErrorMessageListener errorMessageListener) {
+        String newQueueName = null;
+        if (TextUtils.isEmpty(queueName)){
+            newQueueName = createDefaultQueueName(queueName);
+        }else {
+            newQueueName = queueName;
+        }
+        final String finalNewQueueName = newQueueName;
+        executor.execute(() -> {
+            while (isRunning) {
+                try {
+                    rabbitMQ.receiveQueueMessage(finalNewQueueName, message -> {
+                        if (listener != null) listener.receiveMessage(message);
+                    });
+                } catch (IOException | TimeoutException | AlreadyClosedException e) {
+                    if (errorMessageListener!=null){
+                        errorMessageListener.errorMessage(e);
+                    }
+                    e.printStackTrace();
+                    SystemClock.sleep(5000);
+                }
+            }
+        });
+    }
+
+    public void receiveQueueRoutingKeyMessage(String queueName, final String routingKey, final String exchangeName, final String exchangeType, final ReceiveMessageListener listener,final ErrorMessageListener errorMessageListener) {
+        String newQueueName = null;
+        if (TextUtils.isEmpty(queueName)){
+            newQueueName = createDefaultQueueName(queueName);
+        }else {
+            newQueueName = queueName;
+        }
+        final String finalNewQueueName = newQueueName;
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                while (isRunning) {
+                    try {
+                        rabbitMQ.receiveQueueRoutingKeyMessage(finalNewQueueName, routingKey, exchangeName, exchangeType, new RabbitMQClient.ResponseListener() {
+                            @Override
+                            public void receive(String message) {
+                                if (listener != null) listener.receiveMessage(message);
+                            }
+
+                        });
+                    } catch (IOException | TimeoutException | AlreadyClosedException e) {
+                        if (errorMessageListener!=null){
+                            errorMessageListener.errorMessage(e);
+                        }
+                        e.printStackTrace();
+                        SystemClock.sleep(5000);  //等待五秒
+                    }
+                }
+            }
+        });
+    }
+
+    public String createDefaultQueueName(String routingKey) {
+        if (TextUtils.isEmpty(routingKey)){
+            routingKey = "";
+        }
+        return routingKey + "@" + UUID.randomUUID();
+    }
+
+    /**
+     * 建议:
+     * 在application中关闭或者在结束工作时关闭
+     */
+    public void close() {
+        isRunning = false;
+        executor.execute(new Runnable() {
+            @Override
+            public void run() {
+                rabbitMQ.close();
+                executor.shutdownNow();
+            }
+        });
+    }
+
+
+    public interface ReceiveMessageListener {
+        void receiveMessage(String message);
+    }
+
+    public interface SendMessageListener {
+        void sendMessage(boolean isSuccess);
+    }
+
+    public interface ErrorMessageListener{
+        void errorMessage(Exception e);
+    }
+}
+
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/common/SharedPreferencesConfigs.kt b/app/src/main/java/com/bjca/hp/acupuncture/common/SharedPreferencesConfigs.kt
new file mode 100644
index 0000000..8f5eafc
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/common/SharedPreferencesConfigs.kt
@@ -0,0 +1,4 @@
+package com.bjca.hp.acupuncture.common
+
+const val SHARE_RISK_LOCATION = "share_risk_location"
+const val SHARE_RISK_PURE = "share_risk_pure"
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/model/DrugUsage.kt b/app/src/main/java/com/bjca/hp/acupuncture/model/DrugUsage.kt
new file mode 100644
index 0000000..758feda
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/model/DrugUsage.kt
@@ -0,0 +1,72 @@
+package com.bjca.hp.acupuncture.model
+
+import com.google.gson.annotations.SerializedName
+
+data class DrugUsage(
+
+    @field:SerializedName("total")
+    val total: Int,
+
+    @field:SerializedName("size")
+    val size: Int,
+
+    @field:SerializedName("nulls")
+    val nulls: Any,
+
+    @field:SerializedName("index")
+    val index: Int,
+
+    @field:SerializedName("items")
+    val items: List
+)
+
+data class ItemsItem5(
+
+    @field:SerializedName("code")
+    val code: String,
+
+    @field:SerializedName("sysCodes")
+    val sysCodes: Any,
+
+    @field:SerializedName("seqNo")
+    val seqNo: Int,
+
+    @field:SerializedName("memo")
+    val memo: Any,
+
+    @field:SerializedName("global")
+    val global: Boolean,
+
+    @field:SerializedName("type")
+    val type: String,
+
+    @field:SerializedName("parentType")
+    val parentType: Any,
+
+    @field:SerializedName("parentCode")
+    val parentCode: Any,
+
+    @field:SerializedName("codeChain")
+    val codeChain: String,
+
+    @field:SerializedName("ifMaster")
+    val ifMaster: Boolean,
+
+    @field:SerializedName("extra")
+    val extra: Any,
+
+    @field:SerializedName("disabled")
+    val disabled: Boolean,
+
+    @field:SerializedName("lockKey")
+    val lockKey: String,
+
+    @field:SerializedName("id")
+    val id: Int,
+
+    @field:SerializedName("text")
+    val text: String,
+
+    @field:SerializedName("shortCode")
+    val shortCode: String
+)
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/model/ItemsItem.kt b/app/src/main/java/com/bjca/hp/acupuncture/model/ItemsItem.kt
new file mode 100644
index 0000000..8e76657
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/model/ItemsItem.kt
@@ -0,0 +1,71 @@
+package com.bjca.hp.acupuncture.model
+
+
+data class ItemsItems(
+    val assessorName: String,
+    val storehouseCode: String,
+    val sysCode: String,
+    val ifStateExpense: Boolean,
+    val patientId: Int,
+    val usage: String,
+    val medicalAdvice: String,
+    val dosagePerTime: String,
+    val frequency: String,
+    val approveUserId: Int,
+    val itemName: String,
+    val price: Double,
+    val paymentId: Int,
+    val patientAge: String,
+    val cashierId: String,
+    val lockKey: String,
+    val id: Int,
+    val ifInjury: Boolean,
+    val paymentState: String,
+    val invoiceNo: String,
+    val barcode: String,
+    val originalPaymentId: String,
+    val diagnosis: String,
+    val drugRpType: String,
+    val originalInvoiceNo: String,
+    val examineReason: String,
+    val opNo: String,
+    val name: String,
+    val executorDeptCode: String,
+    val assessorCode: String,
+    val refundDate: String,
+    val deptCode: String,
+    val makeMethod: String,
+    val distributeState: String,
+    val rpFeeType: String,
+    val no: String,
+    val settleId: String,
+    val approveDate: String,
+    val originalNo: String,
+    val patientGender: String,
+    val appNo: String,
+    val settleDate: String,
+    val adviceNo: String,
+    val doctorName: String,
+    val rpSettleType: String,
+    val doctorId: Int,
+    val offsetState: String,
+    val disabled: Boolean,
+    val drugRestrict: String,
+    val rpClass: String,
+    val groupNo: String,
+    val cashierName: String,
+    val ifInsurance: Boolean,
+    val examineResult: String,
+    val patientName: String,
+    val dosageUnit: String,
+    val cost: Int,
+    val quantity: String,
+    val ifDivide: String,
+    val excessDrugExplain: String,
+    val approveUserName: String,
+    val rpStatisticType: String,
+    val days: String,
+    val cashierCode: String,
+    val paymentDate: String,
+    val quantityPerDay: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/model/MqMessage.kt b/app/src/main/java/com/bjca/hp/acupuncture/model/MqMessage.kt
new file mode 100644
index 0000000..d95f49e
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/model/MqMessage.kt
@@ -0,0 +1,15 @@
+package com.bjca.hp.acupuncture.model
+
+/***************************************************************************
+ * 

+ * @文件名称:  MqMessage
+ * @包   路   径:  com.bjca.hp.acupuncture.model
+ * @版权所有:北京数字医信责任有限公司 (C) 2022
+ *
+ * @类描述:
+ * @版本: V1.0
+ * @创建人: xuqm
+ * @创建时间:2022/6/20 下午 05:06
+ * @修改记录:
+ */
+data class MqMessage(val no:String)
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/model/RegModel.kt b/app/src/main/java/com/bjca/hp/acupuncture/model/RegModel.kt
new file mode 100644
index 0000000..3195852
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/model/RegModel.kt
@@ -0,0 +1,168 @@
+package com.bjca.hp.acupuncture.model
+
+import com.google.gson.annotations.SerializedName
+
+data class RegModel(
+
+    @field:SerializedName("total")
+    val total: Int,
+
+    @field:SerializedName("size")
+    val size: Int,
+
+    @field:SerializedName("nulls")
+    val nulls: String,
+
+    @field:SerializedName("index")
+    val index: Int,
+
+    @field:SerializedName("items")
+    val items: List
+)
+
+data class ItemsItem3(
+
+    @field:SerializedName("date")
+    val date: String,
+
+    @field:SerializedName("additionUserId")
+    val additionUserId: String,
+
+    @field:SerializedName("deptName")
+    val deptName: String,
+
+    @field:SerializedName("seqNo")
+    val seqNo: Int,
+
+    @field:SerializedName("patientId")
+    val patientId: Int,
+
+    @field:SerializedName("signInDate")
+    val signInDate: String,
+
+    @field:SerializedName("patientGender")
+    val patientGender: String,
+
+    @field:SerializedName("opType")
+    val opType: String,
+
+    @field:SerializedName("ifSubsequent")
+    val ifSubsequent: Boolean,
+
+    @field:SerializedName("registrarName")
+    val registrarName: String,
+
+    @field:SerializedName("ifDoctorAdd")
+    val ifDoctorAdd: Boolean,
+
+    @field:SerializedName("cardNo")
+    val cardNo: String,
+
+    @field:SerializedName("additionUserName")
+    val additionUserName: String,
+
+    @field:SerializedName("treatDate")
+    val treatDate: String,
+
+    @field:SerializedName("takingDate")
+    val takingDate: String,
+
+    @field:SerializedName("ifDeleted")
+    val ifDeleted: Boolean,
+
+    @field:SerializedName("doctorName")
+    val doctorName: String,
+
+    @field:SerializedName("appointmentChannelCode")
+    val appointmentChannelCode: String,
+
+    @field:SerializedName("lineNo")
+    val lineNo: Double,
+
+    @field:SerializedName("doctorId")
+    val doctorId: Int,
+
+    @field:SerializedName("price")
+    val price: Double,
+
+    @field:SerializedName("ifAddition")
+    val ifAddition: Boolean,
+
+    @field:SerializedName("patientAge")
+    val patientAge: String,
+
+    @field:SerializedName("lockKey")
+    val lockKey: String,
+
+    @field:SerializedName("id")
+    val id: Int,
+
+    @field:SerializedName("state")
+    val state: String,
+
+    @field:SerializedName("paymentState")
+    val paymentState: String,
+
+    @field:SerializedName("regType")
+    val regType: String,
+
+    @field:SerializedName("periodEnd")
+    val periodEnd: String,
+
+    @field:SerializedName("registrarId")
+    val registrarId: Int,
+
+    @field:SerializedName("patientName")
+    val patientName: String,
+
+    @field:SerializedName("targetId")
+    val targetId: String,
+
+    @field:SerializedName("cardType")
+    val cardType: String,
+
+    @field:SerializedName("pay")
+    val pay: Double,
+
+    @field:SerializedName("lineId")
+    val lineId: Int,
+
+    @field:SerializedName("occupationalInjury")
+    val occupationalInjury: String,
+
+    @field:SerializedName("version")
+    val version: Int,
+
+    @field:SerializedName("patientPhone")
+    val patientPhone: String,
+
+    @field:SerializedName("ifEmergency")
+    val ifEmergency: Boolean,
+
+    @field:SerializedName("patientLevel")
+    val patientLevel: String,
+
+    @field:SerializedName("periodType")
+    val periodType: String,
+
+    @field:SerializedName("opNo")
+    val opNo: String,
+
+    @field:SerializedName("ifMaternityInsurance")
+    val ifMaternityInsurance: Boolean,
+
+    @field:SerializedName("periodStart")
+    val periodStart: String,
+
+    @field:SerializedName("appointmentDate")
+    val appointmentDate: String,
+
+    @field:SerializedName("appCardType")
+    val appCardType: String,
+
+    @field:SerializedName("deptCode")
+    val deptCode: String,
+
+    @field:SerializedName("appCardNo")
+    val appCardNo: String
+)
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/model/RpDetailModel.kt b/app/src/main/java/com/bjca/hp/acupuncture/model/RpDetailModel.kt
new file mode 100644
index 0000000..4710d52
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/model/RpDetailModel.kt
@@ -0,0 +1,153 @@
+package com.bjca.hp.acupuncture.model
+
+import com.google.gson.annotations.SerializedName
+
+data class RpDetailModel(
+
+    @field:SerializedName("total")
+    val total: Int,
+
+    @field:SerializedName("size")
+    val size: Int,
+
+    @field:SerializedName("nulls")
+    val nulls: String,
+
+    @field:SerializedName("index")
+    val index: Int,
+
+    @field:SerializedName("items")
+    val items: List
+)
+
+data class ItemsItem2(
+
+    @field:SerializedName("shelfIndex")
+    val shelfIndex: String,
+
+    @field:SerializedName("shelfCommand")
+    val shelfCommand: String,
+
+    @field:SerializedName("standard")
+    val standard: String,
+
+    @field:SerializedName("no")
+    val no: String,
+
+    @field:SerializedName("storehouseCode")
+    val storehouseCode: String,
+
+    @field:SerializedName("code")
+    val code: String,
+
+    @field:SerializedName("usage")
+    val usage: String,
+
+    @field:SerializedName("appNo")
+    val appNo: String,
+
+    @field:SerializedName("memo")
+    val memo: String,
+
+    @field:SerializedName("herbalSpecialUsage")
+    val herbalSpecialUsage: String,
+
+    @field:SerializedName("restrict")
+    val restrict: String,
+
+    @field:SerializedName("type")
+    val type: String,
+
+    @field:SerializedName("dosagePerTime")
+    val dosagePerTime: String,
+
+    @field:SerializedName("frequency")
+    val frequency: String,
+
+    @field:SerializedName("insuranceCode")
+    val insuranceCode: String,
+
+    @field:SerializedName("totalDose")
+    val totalDose: String,
+
+    @field:SerializedName("times")
+    val times: String,
+
+    @field:SerializedName("price")
+    val price: Double,
+
+    @field:SerializedName("mnemonic")
+    val mnemonic: String,
+
+    @field:SerializedName("offsetState")
+    val offsetState: String,
+
+    @field:SerializedName("warning")
+    val warning: String,
+
+    @field:SerializedName("lockKey")
+    val lockKey: String,
+
+    @field:SerializedName("id")
+    val id: Int,
+
+    @field:SerializedName("rpClass")
+    val rpClass: String,
+
+    @field:SerializedName("groupNo")
+    val groupNo: String,
+
+    @field:SerializedName("key")
+    val key: String,
+
+    @field:SerializedName("dosageUnit")
+    val dosageUnit: String,
+
+    @field:SerializedName("quantity")
+    val quantity: Int,
+
+    @field:SerializedName("cost")
+    val cost: Double,
+
+    @field:SerializedName("rpNo")
+    val rpNo: String,
+
+    @field:SerializedName("lotNumber")
+    val lotNumber: String,
+
+    @field:SerializedName("manufacturerCode")
+    val manufacturerCode: String,
+
+    @field:SerializedName("approvalNumber")
+    val approvalNumber: String,
+
+    @field:SerializedName("feeType")
+    val feeType: String,
+
+    @field:SerializedName("unit")
+    val unit: String,
+
+    @field:SerializedName("symptom")
+    val symptom: String,
+
+    @field:SerializedName("form")
+    val form: String,
+
+    @field:SerializedName("opNo")
+    val opNo: String,
+
+    @field:SerializedName("name")
+    val name: String,
+
+    @field:SerializedName("parts")
+    val parts: String,
+
+    @field:SerializedName("days")
+    val days: Int,
+
+    @field:SerializedName("executorDeptCode")
+    val executorDeptCode: String,
+
+    @field:SerializedName("offsetId")
+    val offsetId: Any
+)
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/model/RpModel.kt b/app/src/main/java/com/bjca/hp/acupuncture/model/RpModel.kt
new file mode 100644
index 0000000..92d245c
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/model/RpModel.kt
@@ -0,0 +1,21 @@
+package com.bjca.hp.acupuncture.model
+
+import com.google.gson.annotations.SerializedName
+
+data class RpModel(
+
+    @field:SerializedName("total")
+    val total: Int,
+
+    @field:SerializedName("size")
+    val size: Int,
+
+    @field:SerializedName("nulls")
+    val nulls: Any,
+
+    @field:SerializedName("index")
+    val index: Int,
+
+    @field:SerializedName("items")
+    val items: List
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/model/WelcomeLIstModel.kt b/app/src/main/java/com/bjca/hp/acupuncture/model/WelcomeLIstModel.kt
new file mode 100644
index 0000000..f9f475b
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/model/WelcomeLIstModel.kt
@@ -0,0 +1,113 @@
+package com.bjca.hp.acupuncture.model
+
+import com.google.gson.annotations.SerializedName
+import com.xuqm.base.adapter.BaseItem
+import java.util.ArrayList
+
+data class WelcomeLIstModel(
+
+    @field:SerializedName("total")
+    val total: Int? = null,
+
+    @field:SerializedName("size")
+    val size: Int? = null,
+
+    @field:SerializedName("nulls")
+    val nulls: Any? = null,
+
+    @field:SerializedName("index")
+    val index: Int? = null,
+
+    @field:SerializedName("items")
+    val items: ArrayList = arrayListOf()
+)
+
+data class ItemsItem(
+
+    @field:SerializedName("standard")
+    val standard: String? = null,
+
+    @field:SerializedName("storehouseCode")
+    val storehouseCode: String? = null,
+
+    @field:SerializedName("shelfIndex")
+    val shelfIndex: Any? = null,
+
+    @field:SerializedName("code")
+    val code: String? = null,
+
+    @field:SerializedName("purpose")
+    val purpose: String? = null,
+
+    @field:SerializedName("supplierCode")
+    val supplierCode: String? = null,
+
+    @field:SerializedName("herbalSku")
+    val herbalSku: String? = null,
+
+    @field:SerializedName("type")
+    val type: String? = null,
+
+    @field:SerializedName("restrict")
+    val restrict: String? = null,
+
+    @field:SerializedName("rate")
+    val rate: Double? = null,
+
+    @field:SerializedName("price")
+    val price: Double? = null,
+
+    @field:SerializedName("srcId")
+    val srcId: Any? = null,
+
+    @field:SerializedName("disabled")
+    val disabled: Boolean? = null,
+
+    @field:SerializedName("lockKey")
+    val lockKey: Any? = null,
+
+    @field:SerializedName("id")
+    val id: Int? = null,
+
+    @field:SerializedName("applyQuantity")
+    val applyQuantity: Double? = null,
+
+    @field:SerializedName("shortCode")
+    val shortCode: String? = null,
+
+    @field:SerializedName("expirationDate")
+    val expirationDate: String? = null,
+
+    @field:SerializedName("brandName")
+    val brandName: String? = null,
+
+    @field:SerializedName("cost")
+    val cost: Double? = null,
+
+    @field:SerializedName("quantity")
+    val quantity: Double? = null,
+
+    @field:SerializedName("lotNumber")
+    val lotNumber: String? = null,
+
+    @field:SerializedName("manufacturerCode")
+    val manufacturerCode: String? = null,
+
+    @field:SerializedName("feeType")
+    val feeType: Any? = null,
+
+    @field:SerializedName("approvalNumber")
+    val approvalNumber: Any? = null,
+
+    @field:SerializedName("ceilType")
+    val ceilType: String? = null,
+
+    @field:SerializedName("unit")
+    val unit: String? = null,
+
+    @field:SerializedName("form")
+    val form: String? = null,
+
+    @field:SerializedName("name")
+    val name: String? = null
+) : BaseItem()
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/receiver/BootCompleteReceiver.kt b/app/src/main/java/com/bjca/hp/acupuncture/receiver/BootCompleteReceiver.kt
new file mode 100644
index 0000000..078d9e2
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/receiver/BootCompleteReceiver.kt
@@ -0,0 +1,30 @@
+package com.bjca.hp.acupuncture.receiver
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import com.bjca.hp.acupuncture.ui.MainActivity
+
+/***************************************************************************
+ * 

+ * @文件名称:  BootCompleteReceiver
+ * @包   路   径:  com.bjca.hp.acupuncture.receiver
+ * @版权所有:北京数字医信责任有限公司 (C) 2022
+ *
+ * @类描述:
+ * @版本: V1.0
+ * @创建人: xuqm
+ * @创建时间:2022/6/24 下午 06:34
+ * @修改记录:
+ */
+class BootCompleteReceiver : BroadcastReceiver(){
+    override fun onReceive(context: Context, intent: Intent) {
+        if(Intent.ACTION_BOOT_COMPLETED == intent.action){
+            val thisIntent = Intent(context, MainActivity::class.java)
+            thisIntent.action = "android.intent.action.MAIN";
+            thisIntent.addCategory("android.intent.category.LAUNCHER");
+            thisIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK;
+            context.startActivity(thisIntent);
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/repository/HeaderInterceptor.kt b/app/src/main/java/com/bjca/hp/acupuncture/repository/HeaderInterceptor.kt
new file mode 100644
index 0000000..6039475
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/repository/HeaderInterceptor.kt
@@ -0,0 +1,130 @@
+package com.bjca.hp.acupuncture.repository
+
+import android.content.Context
+import com.xuqm.base.common.SHARE_UESR_TOKEN
+import com.xuqm.base.extensions.getStringForPreferences
+import com.xuqm.base.extensions.log
+import com.xuqm.base.extensions.loge
+import okhttp3.Headers
+import okhttp3.Interceptor
+import okhttp3.Response
+import okhttp3.internal.http.HttpHeaders
+import okhttp3.internal.http.StatusLine
+import okio.Buffer
+import okio.BufferedSource
+import okio.GzipSource
+import java.io.EOFException
+import java.net.HttpURLConnection
+import java.nio.charset.Charset
+
+
+class HeaderInterceptor(val context: Context) : Interceptor {
+    val UTF8 = Charset.forName("UTF-8")
+    override fun intercept(chain: Interceptor.Chain): Response {
+        val original = chain.request()
+
+        //请求定制:添加请求头
+        val requestBuilder = original.newBuilder()
+            .header("Authentication", context.getStringForPreferences(SHARE_UESR_TOKEN))
+            .addHeader("Content-Type", "application/json;charset=UTF-8")
+
+//        context.getStringForPreferences(SHARE_UESR_TOKEN).loge()
+
+        val request = requestBuilder.build()
+        "${request.url()}(${request.method()})".loge()
+
+        val headers = request.headers()
+
+//        request.body()?.also {
+//
+//            if (!bodyHasUnknownEncoding(headers)) {
+//                val buffer = Buffer()
+//                it.writeTo(buffer)
+//
+//                var charset = Charset.forName("UTF-8")
+//                it.contentType()?.also { its -> charset = its.charset(Charset.forName("UTF-8"))!! }
+//
+////                if (isPlaintext(buffer)) {
+////                    buffer.readString(charset).loge()
+////                }
+//            }
+//        }
+        val response = chain.proceed(request)
+
+        response.body()?.also {
+            if (!bodyHasUnknownEncoding(headers) && hasBody(response)) {
+                val source: BufferedSource = it.source()
+                source.request(Long.MAX_VALUE) // Buffer the entire body.
+                var buffer = source.buffer
+                if ("gzip".equals(headers.get("Content-Encoding"), ignoreCase = true)) {
+                    var gzippedResponseBody: GzipSource? = null
+                    try {
+                        gzippedResponseBody = GzipSource(buffer.clone())
+                        buffer = Buffer()
+                        buffer.writeAll(gzippedResponseBody)
+                    } finally {
+                        gzippedResponseBody?.close()
+                    }
+                }
+                var charset = UTF8
+                it.contentType()?.also { its -> charset = its.charset(Charset.forName("UTF-8"))!! }
+
+
+                if (isPlaintext(buffer)) {
+                    buffer.clone().readString(charset).log()
+                }
+            }
+        }
+
+
+
+
+        return response
+    }
+
+    private fun bodyHasUnknownEncoding(headers: Headers): Boolean {
+        val contentEncoding = headers["Content-Encoding"]
+        return (contentEncoding != null && !contentEncoding.equals("identity", ignoreCase = true)
+                && !contentEncoding.equals("gzip", ignoreCase = true))
+    }
+
+    private fun isPlaintext(buffer: Buffer): Boolean {
+        return try {
+            val prefix = Buffer()
+            val byteCount = if (buffer.size < 64) buffer.size else 64
+            buffer.copyTo(prefix, 0, byteCount)
+            for (i in 0..15) {
+                if (prefix.exhausted()) {
+                    break
+                }
+                val codePoint = prefix.readUtf8CodePoint()
+                if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
+                    return false
+                }
+            }
+            true
+        } catch (e: EOFException) {
+            false // Truncated UTF-8 sequence.
+        }
+    }
+
+    fun hasBody(response: Response): Boolean {
+        // HEAD requests never yield a body regardless of the response headers.
+        if (response.request().method() == "HEAD") {
+            return false
+        }
+        val responseCode = response.code()
+        if ((responseCode < StatusLine.HTTP_CONTINUE || responseCode >= 200)
+            && responseCode != HttpURLConnection.HTTP_NO_CONTENT && responseCode != HttpURLConnection.HTTP_NOT_MODIFIED
+        ) {
+            return true
+        }
+
+        // If the Content-Length or Transfer-Encoding headers disagree with the response code, the
+        // response is malformed. For best compatibility, we honor the headers.
+        return HttpHeaders.contentLength(response) != -1L || "chunked".equals(
+            response.header("Transfer-Encoding"),
+            ignoreCase = true
+        )
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/repository/Service.kt b/app/src/main/java/com/bjca/hp/acupuncture/repository/Service.kt
new file mode 100644
index 0000000..952d787
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/repository/Service.kt
@@ -0,0 +1,30 @@
+package com.bjca.hp.acupuncture.repository
+
+import com.bjca.hp.acupuncture.model.*
+import com.xuqm.sdhbwfu.core.model.HttpResult
+import io.reactivex.Observable
+import retrofit2.http.GET
+import retrofit2.http.Path
+import retrofit2.http.Query
+
+
+interface Service {
+    @GET("drug/stock/standard?storehouseCode=2&type=&form=&purpose=&restrict=&danger=&antibiotic=&keyword=&manufacturerCode=&supplierCode=&expirationDateMin=&expirationDateMax=&sort=id&asc=false&papeIndexOnView=2&pageSize=20&tenantId=101")
+    fun standard(@Query("pageIndex") pageIndex: Int): Observable
+
+    // op/rp?no=CF220609004247&rpClass=药品&tenantId=101
+    @GET("op/rp?rpClass=药品&tenantId=101")
+    fun rp(@Query("no") no: String): Observable
+
+    // op/rpDetail?opNo=MZ220321036030&rpNo=CF220323001947&tenantId=101
+    @GET("op/rpDetail?tenantId=101")
+    fun rpDetail(@Query("opNo") opNo: String, @Query("rpNo") rpNo: String): Observable
+
+    // op/reg?opNo=MZ220321036030&tenantId=101
+    @GET("op/reg?tenantId=101")
+    fun reg(@Query("opNo") opNo: String): Observable
+
+    // dict/DrugUsage?sort=id&asc=false&pageIndexOnView=1&pageSize=100&dictType=DrugType&pageIndex=0
+    @GET("dict/DrugUsage?sort=id&asc=false&pageIndexOnView=1&pageSize=100&dictType=DrugType&pageIndex=0")
+    fun drugUsage(): Observable
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/ui/MainActivity.kt b/app/src/main/java/com/bjca/hp/acupuncture/ui/MainActivity.kt
new file mode 100644
index 0000000..e7c3af6
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/ui/MainActivity.kt
@@ -0,0 +1,243 @@
+package com.bjca.hp.acupuncture.ui
+
+import android.graphics.Typeface
+import android.os.Bundle
+import androidx.activity.viewModels
+import com.bigkoo.alertview.AlertView
+import com.bjca.hp.acupuncture.MyApplication
+import com.bjca.hp.acupuncture.R
+import com.bjca.hp.acupuncture.databinding.ActivityMainBinding
+import com.bjca.hp.acupuncture.model.ItemsItem2
+import com.bjca.hp.acupuncture.model.ItemsItem3
+import com.bjca.hp.acupuncture.model.ItemsItem5
+import com.bjca.hp.acupuncture.model.ItemsItems
+import com.bjca.hp.acupuncture.viewmodel.MainVM
+import com.xuqm.base.adapter.CommonAdapter
+import com.xuqm.base.adapter.ViewHolder
+import com.xuqm.base.dialog.loading.LoadingDialog
+import com.xuqm.base.extensions.loge
+import com.xuqm.base.ui.BaseActivity
+import com.xuqm.sdhbwfu.core.extensions.linearLayoutManager
+import com.xuqm.sdhbwfu.core.extensions.showMessage
+import tp.xmaihh.serialport.SerialHelper
+import tp.xmaihh.serialport.bean.ComBean
+
+class MainActivity : BaseActivity() {
+    override fun fullscreen(): Boolean = true
+    override fun getLayoutId(): Int = R.layout.activity_main
+
+    private val vm: MainVM by viewModels()
+
+    override fun initView(savedInstanceState: Bundle?) {
+        super.initView(savedInstanceState)
+
+
+        sourceHanSansCNBold =
+            Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Bold.ttf")
+        sourceHanSansCNMedium =
+            Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Medium.ttf")
+        sourceHanSansCNNormal =
+            Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Normal.ttf")
+        sourceHanSansCNRegular =
+            Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Regular.ttf")
+        din =
+            Typeface.createFromAsset(mContext?.assets, "fonts/DIN-Alternate-Bold.ttf")
+
+        binding.title.typeface = sourceHanSansCNBold
+        binding.name.typeface = sourceHanSansCNBold
+        binding.tags.typeface = sourceHanSansCNMedium
+        binding.btn.typeface = sourceHanSansCNBold
+
+        binding.title1.typeface = sourceHanSansCNMedium
+        binding.title2.typeface = sourceHanSansCNMedium
+        binding.title3.typeface = sourceHanSansCNMedium
+        binding.title5.typeface = sourceHanSansCNMedium
+
+        binding.n1.typeface = sourceHanSansCNRegular
+        binding.v1.typeface = sourceHanSansCNRegular
+        binding.n2.typeface = sourceHanSansCNRegular
+        binding.v2.typeface = sourceHanSansCNRegular
+        binding.n3.typeface = sourceHanSansCNRegular
+        binding.v3.typeface = sourceHanSansCNRegular
+        binding.n4.typeface = sourceHanSansCNRegular
+        binding.v4.typeface = sourceHanSansCNRegular
+        binding.n5.typeface = sourceHanSansCNRegular
+        binding.v5.typeface = sourceHanSansCNRegular
+        binding.n6.typeface = sourceHanSansCNRegular
+        binding.v6.typeface = sourceHanSansCNRegular
+        binding.n7.typeface = sourceHanSansCNRegular
+        binding.v7.typeface = sourceHanSansCNRegular
+        binding.n8.typeface = sourceHanSansCNRegular
+        binding.v8.typeface = sourceHanSansCNRegular
+        binding.n9.typeface = sourceHanSansCNRegular
+        binding.v9.typeface = sourceHanSansCNRegular
+        binding.n10.typeface = sourceHanSansCNRegular
+        binding.v10.typeface = sourceHanSansCNRegular
+        binding.n11.typeface = sourceHanSansCNRegular
+        binding.v11.typeface = sourceHanSansCNRegular
+        binding.n12.typeface = sourceHanSansCNRegular
+        binding.v12.typeface = sourceHanSansCNRegular
+        binding.n13.typeface = sourceHanSansCNRegular
+        binding.v13.typeface = sourceHanSansCNRegular
+        binding.n14.typeface = sourceHanSansCNRegular
+        binding.v14.typeface = sourceHanSansCNRegular
+        binding.n15.typeface = sourceHanSansCNRegular
+        binding.v15.typeface = sourceHanSansCNRegular
+        binding.n16.typeface = sourceHanSansCNRegular
+        binding.v16.typeface = sourceHanSansCNRegular
+        binding.n17.typeface = sourceHanSansCNRegular
+        binding.v17.typeface = sourceHanSansCNRegular
+
+
+        binding.list.linearLayoutManager(mContext, 15)
+        binding.list.adapter = adapter
+
+
+        binding.btn.setOnClickListener {
+            LoadingDialog.showDialog("")
+
+            if (adapter.datas.size > 0)
+                sndMessage(0)
+            else {
+//                s.sendHex("0105002cff004DF3");  // 发送Hex
+
+                MyApplication.getInstance().runOnUiThreadDelay({
+                    try {
+                        s.sendHex("02050001ff00DDC9");  // 发送Hex
+                    } catch (e: Exception) {
+                        e.showMessage()
+                    }
+                    LoadingDialog.dismissDialog()
+                }, 500)
+            }
+        }
+
+    }
+
+    private fun sndMessage(i: Int) {
+        if (i >= adapter.datas.size) {
+            LoadingDialog.dismissDialog()
+            AlertView(
+                "取药完成", adapter.datas.map { it.shelfIndex}.joinToString(), null, arrayOf("确定"), null, mContext,
+                AlertView.Style.Alert
+            ) { _, _ ->
+                mContext.finish()
+            }.show()
+            return
+        }
+        try {
+            s.sendHex(adapter.datas[i].shelfCommand);  // 发送Hex
+        } catch (e: Exception) {
+            e.showMessage()
+        }
+        MyApplication.getInstance().runOnUiThreadDelay({
+            sndMessage(i + 1)
+        }, 2300)
+
+    }
+
+    lateinit var sourceHanSansCNBold: Typeface
+    lateinit var sourceHanSansCNMedium: Typeface
+    lateinit var sourceHanSansCNNormal: Typeface
+    lateinit var sourceHanSansCNRegular: Typeface
+    lateinit var din: Typeface
+
+    var rp: ItemsItems? = null
+    var regM: ItemsItem3? = null
+    var usages: List = listOf()
+    lateinit var s: SerialHelper
+    override fun initData() {
+        super.initData()
+        s = object : SerialHelper("/dev/ttyS0", 38400) {
+            override fun onDataReceived(paramComBean: ComBean?) {
+                paramComBean?.bRec?.loge()
+            }
+        }
+        try {
+            s.open()
+        } catch (e: Exception) {
+            e.showMessage()
+        }
+
+        vm.status.observe(this) {
+            rp = it
+            rerresh()
+        }
+        vm.regM.observe(this) {
+            regM = it
+            rerresh()
+        }
+        vm.usages.observe(this) {
+            usages = it ?: listOf()
+            intent.getStringExtra("opNo")?.let { it1 -> vm.getRp(it1) }
+        }
+        vm.rpDetail.observe(this) {
+            adapter.setmDatas(it)
+        }
+        vm.drugUsage()
+    }
+
+    fun getUsage(code: String): String {
+        var text = "--"
+        usages.forEach {
+            if (it.code == code) {
+                text = it.text
+            }
+        }
+        return text
+    }
+
+    private fun rerresh() {
+        rp?.let {
+            binding.v8.text = it.diagnosis
+            binding.v14.text = it.doctorName
+            binding.v16.text = "${it.price}元"
+            binding.v13.text = it.approveUserName
+            binding.v11.text = it.no
+        }
+        regM?.let {
+            binding.v1.text = it.patientName
+            binding.v2.text = it.patientGender
+            binding.v3.text = "${it.patientAge}"
+            binding.v4.text = it.patientPhone
+            binding.v5.text = ""
+
+            binding.v6.text = it.appCardNo
+            binding.v7.text = it.deptName
+            binding.v9.text = it.date
+            binding.v10.text = it.opType
+
+        }
+    }
+
+
+    private val adapter = object : CommonAdapter(R.layout.item_main) {
+        override fun convert(holder: ViewHolder, item: ItemsItem2, position: Int) {
+
+            holder.setTypeface(R.id.index, sourceHanSansCNMedium)
+                .setText(R.id.index, "${position + 1}")
+                .setTypeface(R.id.n1, sourceHanSansCNRegular)
+                .setTypeface(R.id.v1, sourceHanSansCNRegular)
+                .setText(R.id.v1, item.name)//名称
+                .setTypeface(R.id.n2, sourceHanSansCNRegular)
+                .setTypeface(R.id.v1, sourceHanSansCNRegular)
+                .setText(R.id.v2, item.standard)//规格
+                .setTypeface(R.id.n3, sourceHanSansCNRegular)
+                .setTypeface(R.id.v3, sourceHanSansCNRegular)
+                .setText(R.id.v3, "${item.quantity}${item.unit}")//数量
+                .setTypeface(R.id.n4, sourceHanSansCNRegular)
+                .setTypeface(R.id.v4, sourceHanSansCNRegular)
+                .setText(R.id.v4, getUsage(item.usage))//使用方法---码表
+                .setTypeface(R.id.n5, sourceHanSansCNRegular)
+                .setTypeface(R.id.v5, sourceHanSansCNRegular)
+                .setText(R.id.v5, "${item.dosagePerTime}${item.dosageUnit}")//用量
+                .setTypeface(R.id.n6, sourceHanSansCNRegular)
+                .setTypeface(R.id.v6, sourceHanSansCNRegular)
+                .setText(R.id.v6, item.frequency)//频次---码表
+                .setTypeface(R.id.n7, sourceHanSansCNRegular)
+                .setTypeface(R.id.v7, sourceHanSansCNRegular)
+                .setText(R.id.v7, "${item.days}天")//使用周期
+
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/ui/SettingActivity.kt b/app/src/main/java/com/bjca/hp/acupuncture/ui/SettingActivity.kt
new file mode 100644
index 0000000..a02d486
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/ui/SettingActivity.kt
@@ -0,0 +1,209 @@
+package com.bjca.hp.acupuncture.ui
+
+import android.os.Bundle
+import com.bjca.hp.acupuncture.MyApplication
+import com.bjca.hp.acupuncture.R
+import com.bjca.hp.acupuncture.databinding.ActivitySettingBinding
+import com.xuqm.base.extensions.loge
+import com.xuqm.base.ui.BaseActivity
+import com.xuqm.sdhbwfu.core.extensions.showMessage
+import kotlinx.android.synthetic.main.activity_setting.*
+import tp.xmaihh.serialport.SerialHelper
+import tp.xmaihh.serialport.bean.ComBean
+import java.util.*
+
+class SettingActivity : BaseActivity() {
+    override fun getLayoutId(): Int = R.layout.activity_setting
+    override fun initView(savedInstanceState: Bundle?) {
+        super.initView(savedInstanceState)
+        binding.a13.setOnClickListener {
+
+            val a11 = binding.a11.text.toString().toInt()
+            if (a11 <= 0 || a11 > 9) {
+                "请输入正确的柜号,从1开始".showMessage()
+                return@setOnClickListener
+            }
+            val a12 = binding.a12.text.toString().toInt()
+            if (a12 <= 0) {
+                "请输入正确的柜门号,从1开始".showMessage()
+                return@setOnClickListener
+            }
+            val b1 = "0${a11}05${intToHex(a12, 4)}ff00"
+            val b2 = getCRC(b1)
+            try {
+                s.sendHex("${b1}${b2}");  // 发送Hex
+            } catch (e: Exception) {
+                e.showMessage()
+            }
+
+        }
+        binding.a24.setOnClickListener {
+
+            val a21 = binding.a21.text.toString().toInt()
+            if (a21 <= 0 || a21 > 9) {
+                "请输入正确的柜号,从1开始".showMessage()
+                return@setOnClickListener
+            }
+            val a22 = binding.a22.text.toString().toInt()
+            if (a22 <= 0) {
+                "请输入正确的柜门号,从1开始".showMessage()
+                return@setOnClickListener
+            }
+            val a23 = binding.a23.text.toString().toInt()
+            if (a23 <= 0) {
+                "请输入正确的柜门号,从1开始".showMessage()
+                return@setOnClickListener
+            }
+
+            sndMessage(a21, a22, a23)
+
+        }
+        binding.a31.setOnClickListener {
+            sndMessage(1, 1, 84)
+        }
+        binding.a32.setOnClickListener {
+            sndMessage(2, 1, 84)
+        }
+        binding.a33.setOnClickListener {
+            sndMessage(3, 1, 84)
+        }
+    }
+
+
+    private fun sndMessage(i: Int, ii: Int, iii: Int) {
+        if (ii > iii) return
+        val b1 = "0${i}05${intToHex(ii, 4)}ff00"
+        val b2 = getCRC(b1)
+        try {
+            s.sendHex("${b1}${b2}");  // 发送Hex
+        } catch (e: Exception) {
+            e.showMessage()
+        }
+        MyApplication.getInstance().runOnUiThreadDelay({
+            sndMessage(i, ii + 1, iii)
+        }, 2300)
+
+    }
+
+
+    lateinit var s: SerialHelper
+    override fun initData() {
+        super.initData()
+        s = object : SerialHelper("/dev/ttyS0", 38400) {
+            override fun onDataReceived(paramComBean: ComBean?) {
+                paramComBean?.bRec?.loge()
+            }
+        }
+        try {
+            s.open()
+        } catch (e: Exception) {
+            e.showMessage()
+        }
+    }
+
+    /**
+     * 10进制转16进制.
+     *
+     * @param n    10进制数
+     * @param size 转换后的16进制位数
+     * @return 转换结果
+     */
+    private fun intToHex(n: Int, size: Int): String {
+        var n = n
+        var s = StringBuffer()
+        var a: String
+        val b = charArrayOf(
+            '0',
+            '1',
+            '2',
+            '3',
+            '4',
+            '5',
+            '6',
+            '7',
+            '8',
+            '9',
+            'A',
+            'B',
+            'C',
+            'D',
+            'E',
+            'F'
+        )
+        while (n != 0) {
+            s = s.append(b[n % 16])
+            n = n / 16
+        }
+        a = s.reverse().toString()
+        a = add_zero(a, size)
+        return a
+    }
+
+    fun add_zero(str: String, size: Int): String {
+        var str = str
+        if (str.length < size) {
+            str = "0$str"
+            str = add_zero(str, size)
+        }
+        return str
+    }
+
+
+    fun getCRC(data: String): String {
+        var data = data
+        data = data.replace(" ", "")
+        val len = data.length
+        if (len % 2 != 0) {
+            return "0000"
+        }
+        val num = len / 2
+        val para = ByteArray(num)
+        for (i in 0 until num) {
+            val value = Integer.valueOf(data.substring(i * 2, 2 * (i + 1)), 16)
+            para[i] = value.toByte()
+        }
+        return getCRC(para)
+    }
+
+    /**
+     * 计算CRC16校验码
+     *
+     * @param bytes
+     * 字节数组
+     * @return [String] 校验码
+     * @since 1.0
+     */
+    fun getCRC(bytes: ByteArray): String {
+        // CRC寄存器全为1
+        var CRC = 0x0000ffff
+        // 多项式校验值
+        val POLYNOMIAL = 0x0000a001
+        var i: Int
+        var j: Int
+        i = 0
+        while (i < bytes.size) {
+            CRC = CRC xor (bytes[i].toInt() and 0x000000ff)
+            j = 0
+            while (j < 8) {
+                if (CRC and 0x00000001 != 0) {
+                    CRC = CRC shr 1
+                    CRC = CRC xor POLYNOMIAL
+                } else {
+                    CRC = CRC shr 1
+                }
+                j++
+            }
+            i++
+        }
+        // 结果转换为16进制
+        var result = Integer.toHexString(CRC).uppercase(Locale.getDefault())
+        if (result.length != 4) {
+            val sb = StringBuffer("0000")
+            result = sb.replace(4 - result.length, 4, result).toString()
+        }
+        //高位在前地位在后
+        //return result.substring(2, 4) + " " + result.substring(0, 2);
+        // 交换高低位,低位在前高位在后
+        return result.substring(2, 4) + result.substring(0, 2)
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/ui/TestActivity.kt b/app/src/main/java/com/bjca/hp/acupuncture/ui/TestActivity.kt
new file mode 100644
index 0000000..b9bafb2
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/ui/TestActivity.kt
@@ -0,0 +1,36 @@
+package com.bjca.hp.acupuncture.ui
+
+import android.os.Build.VERSION_CODES.R
+import android.os.Bundle
+import com.bjca.hp.acupuncture.R
+import com.bjca.hp.acupuncture.databinding.ActivityTestBinding
+import com.xuqm.base.common.ToolsHelper
+import com.xuqm.base.extensions.getStringForPreferences
+import com.xuqm.base.extensions.putString
+import com.xuqm.base.ui.BaseActivity
+import com.xuqm.base.web.XWebViewHelper
+
+class TestActivity : BaseActivity() {
+    override fun getLayoutId(): Int = R.layout.activity_test
+    override fun initView(savedInstanceState: Bundle?) {
+        super.initView(savedInstanceState)
+
+        val str = getStringForPreferences("wurl")
+        if (!ToolsHelper.isNull(str))
+            binding.editUrl.setText(str)
+
+        binding.btn.setOnClickListener {
+
+            val url =
+                if (ToolsHelper.isNull(binding.editUrl.text)) "https://web.sdk.qcloud.com/trtc/webrtc/demo/quick-demo-vue3-ts/index.html#/"
+                else binding.editUrl.text.toString()
+
+            putString("wurl", url)
+            XWebViewHelper.startWebNoTopBar(
+                mContext,
+                url
+            )
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/ui/WelcomeActivity.kt b/app/src/main/java/com/bjca/hp/acupuncture/ui/WelcomeActivity.kt
new file mode 100644
index 0000000..396339d
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/ui/WelcomeActivity.kt
@@ -0,0 +1,166 @@
+package com.bjca.hp.acupuncture.ui
+
+import android.content.Intent
+import android.graphics.Typeface
+import android.os.Bundle
+import com.bjca.hp.acupuncture.R
+import com.bjca.hp.acupuncture.common.RabbitMQUtil
+import com.bjca.hp.acupuncture.databinding.ActivityWelcomeBinding
+import com.bjca.hp.acupuncture.model.ItemsItem
+import com.bjca.hp.acupuncture.viewmodel.WelcomeVM
+import com.xuqm.base.adapter.BasePagedAdapter
+import com.xuqm.base.adapter.CommonPagedAdapter
+import com.xuqm.base.adapter.ViewHolder
+import com.xuqm.base.ui.BaseListFormLayoutActivity
+import com.xuqm.sdhbwfu.core.extensions.gridLayoutManager
+import com.xuqm.sdhbwfu.core.extensions.runWithPermission
+import com.xuqm.sdhbwfu.core.extensions.toStrings
+
+class WelcomeActivity : BaseListFormLayoutActivity() {
+
+    override fun getLayoutId(): Int = R.layout.activity_welcome
+    override fun fullscreen(): Boolean = true
+
+//    lateinit var s: SerialHelper
+
+    lateinit var sourceHanSansCNBold: Typeface
+    lateinit var sourceHanSansCNMedium: Typeface
+    lateinit var sourceHanSansCNNormal: Typeface
+    lateinit var din: Typeface
+    lateinit var mq: RabbitMQUtil
+
+    private var oldTime = 0L
+    private var index = 0
+
+    override fun initView(savedInstanceState: Bundle?) {
+        super.initView(savedInstanceState)
+
+        sourceHanSansCNBold =
+            Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Bold.ttf")
+        sourceHanSansCNMedium =
+            Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Medium.ttf")
+        sourceHanSansCNNormal =
+            Typeface.createFromAsset(mContext?.assets, "fonts/SourceHanSansCN-Normal.ttf")
+        din =
+            Typeface.createFromAsset(mContext?.assets, "fonts/DIN-Alternate-Bold.ttf")
+
+
+        binding.title.typeface = sourceHanSansCNBold
+
+        binding.title.setOnClickListener {
+            val newTime = System.currentTimeMillis()
+            if (newTime - oldTime < 2500 && oldTime != 0L) {
+                if (index > 5) {
+                    startActivity(Intent(mContext, SettingActivity::class.java))
+                    index = 0
+                }
+                index++
+            } else {
+                oldTime = newTime
+                index = 0
+            }
+        }
+
+//        binding.list.gridLayoutManager(mContext, 6, 2)
+//        binding.list.adapter = adapter
+
+//        adapter.setmDatas(arrayListOf("空调", "水泵", "空气净化器", "阳台", "灯"))
+        recyclerView.gridLayoutManager(mContext, 21, 3)
+
+
+        adapter.setItemLongClickListener { _, _, _ ->
+            startActivity(Intent(mContext, MainActivity::class.java))
+            return@setItemLongClickListener true
+        }
+
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        mq.close()
+    }
+
+    override fun initData() {
+        super.initData()
+
+
+        runWithPermission(
+            "android.permission.MODIFY_AUDIO_SETTINGS",
+            "android.permission.RECORD_AUDIO",
+            "android.permission.CAMERA"
+        ) {
+            startActivity(Intent(mContext, TestActivity::class.java))
+        }
+
+//        XWebViewHelper.startWebNoTopBar(mContext,"https://mdtdemo.51trust.com/")
+//        mq = RabbitMQUtil("10.10.202.11", 5672, "guest", "guest")
+//
+//        mq.receiveQueueMessage("RpNoByMedicineCabinet",
+//            {
+//
+//                startActivity(Intent(mContext, MainActivity::class.java)
+//                    .apply {
+//                        putExtra(
+//                            "opNo",
+//                            GsonImplHelp.get().toObject(it, MqMessage::class.java).no
+//                        )
+//                    })
+//            }
+//        ) {
+//            it.loge()
+//        }
+
+//        s = object : SerialHelper("/dev/ttyS0", 38400) {
+//            override fun onDataReceived(paramComBean: ComBean?) {
+//                paramComBean?.bRec?.loge()
+//            }
+//
+//        }
+//        s.setStickPackageHelper {
+//            try {
+//                val available = it.available()
+//                if (available > 0) {
+//                    val buffer = ByteArray(available)
+//                    val size = it.read(buffer)
+//                    if (size > 0) {
+//                        return@setStickPackageHelper buffer;
+//                    }
+//                } else {
+//                    SystemClock.sleep(50);
+//                }
+//
+//            } catch (e: IOException) {
+//                e.printStackTrace();
+//            }
+//            return@setStickPackageHelper null
+//        }
+
+//        s.sendHex("02050001ff00DDC9");  // 发送Hex
+
+    }
+
+
+    private val adapter = object : CommonPagedAdapter(R.layout.item_welcome) {
+        override fun convert(holder: ViewHolder, item: ItemsItem, position: Int) {
+            holder
+                .setTypeface(R.id.index, sourceHanSansCNMedium)
+                .setTypeface(R.id.name, sourceHanSansCNBold)
+                .setTypeface(R.id.hint, sourceHanSansCNNormal)
+                .setTypeface(R.id.number, din)
+                .setTypeface(R.id.unit, sourceHanSansCNNormal)
+                .setTypeface(R.id.balance, sourceHanSansCNNormal)
+                .setText(R.id.index, "${position + 1}")
+                .setText(R.id.name, item.name)
+                .setText(R.id.hint, item.supplierCode)
+                .setText(R.id.number, item.price?.toStrings())
+                .setText(R.id.unit, "元/${item.unit}")
+                .setText(R.id.balance, "剩余:${item.quantity}${item.unit}")
+
+
+        }
+    }
+
+    override fun adapter(): BasePagedAdapter = adapter
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/viewmodel/MainVM.kt b/app/src/main/java/com/bjca/hp/acupuncture/viewmodel/MainVM.kt
new file mode 100644
index 0000000..187bcd9
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/viewmodel/MainVM.kt
@@ -0,0 +1,104 @@
+package com.bjca.hp.acupuncture.viewmodel
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.bjca.hp.acupuncture.MyApplication
+import com.bjca.hp.acupuncture.model.ItemsItem2
+import com.bjca.hp.acupuncture.model.ItemsItem3
+import com.bjca.hp.acupuncture.model.ItemsItem5
+import com.bjca.hp.acupuncture.model.ItemsItems
+import com.bjca.hp.acupuncture.repository.Service
+import com.xuqm.base.di.manager.HttpManager
+import com.xuqm.base.extensions.showMessage
+import com.xuqm.sdhbwfu.core.viewModel.BaseViewModel
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+
+/***************************************************************************
+ * 

+ * @文件名称:  WelcomeVM
+ * @包   路   径:  com.bjca.hp.acupuncture.viewmodel
+ * @版权所有:北京数字医信责任有限公司 (C) 2022
+ *
+ * @类描述:
+ * @版本: V1.0
+ * @创建人: xuqm
+ * @创建时间:2022/6/17 下午 02:33
+ * @修改记录:
+ */
+class MainVM : BaseViewModel() {
+
+
+    private val _status = MutableLiveData()
+    val status: LiveData = _status
+
+    fun getRp(opNo:String = "CF220609004247" ) {
+        HttpManager.getApi(MyApplication.appComponent1, Service::class.java)
+            .rp(opNo)
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .subscribe(
+                {
+                    _status.postValue(it.items[0])
+                    rpDetail(it.items[0].opNo, it.items[0].no)
+                    reg(it.items[0].opNo)
+                }, {
+                    _status.postValue(null)
+                    showMessage(it.toString())
+                }
+            ).adds()
+    }
+
+    private val _rpDetail = MutableLiveData>()
+    val rpDetail: LiveData> = _rpDetail
+
+    fun rpDetail(opNo: String, rpNo: String) {
+        HttpManager.getApi(MyApplication.appComponent1, Service::class.java)
+            .rpDetail(opNo, rpNo)
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .subscribe(
+                {
+                    _rpDetail.postValue(it.items)
+                }, {
+                    _rpDetail.postValue(null)
+                    showMessage(it.toString())
+                }
+            ).adds()
+    }
+
+    private val _regM = MutableLiveData()
+    val regM: LiveData = _regM
+    fun reg(opNo: String) {
+        HttpManager.getApi(MyApplication.appComponent1, Service::class.java)
+            .reg(opNo)
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .subscribe(
+                {
+                    _regM.postValue(it?.items?.get(0))
+                }, {
+                    _regM.postValue(null)
+                    showMessage(it.toString())
+                }
+            ).adds()
+    }
+
+    private val _usages = MutableLiveData>()
+    val usages: LiveData> = _usages
+    fun drugUsage() {
+        HttpManager.getApi(MyApplication.appComponent2, Service::class.java)
+            .drugUsage()
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .subscribe(
+                {
+                    _usages.postValue(it.items)
+                }, {
+                    _usages.postValue(null)
+                    showMessage(it.toString())
+                }
+            ).adds()
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/viewmodel/WelcomeVM.kt b/app/src/main/java/com/bjca/hp/acupuncture/viewmodel/WelcomeVM.kt
new file mode 100644
index 0000000..b226475
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/viewmodel/WelcomeVM.kt
@@ -0,0 +1,40 @@
+package com.bjca.hp.acupuncture.viewmodel
+
+import com.bjca.hp.acupuncture.model.ItemsItem
+import com.bjca.hp.acupuncture.repository.Service
+import com.xuqm.base.di.manager.HttpManager
+import com.xuqm.base.extensions.showMessage
+import com.xuqm.base.viewmodel.BaseListViewModel
+import com.xuqm.base.viewmodel.callback.Response
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+
+/***************************************************************************
+ * 

+ * @文件名称:  WelcomeVM
+ * @包   路   径:  com.bjca.hp.acupuncture.viewmodel
+ * @版权所有:北京数字医信责任有限公司 (C) 2022
+ *
+ * @类描述:
+ * @版本: V1.0
+ * @创建人: xuqm
+ * @创建时间:2022/6/17 下午 02:33
+ * @修改记录:
+ */
+class WelcomeVM : BaseListViewModel() {
+    override fun loadData(page: Int, onResponse: Response) {
+        add(
+            HttpManager.getApi(Service::class.java)
+                .standard(page)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(
+                    {
+                        onResponse.onResponse(it.items)
+                    }, {
+                        onResponse.onResponse(null)
+//                        showMessage(it)
+                    }
+                ))
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bjca/hp/acupuncture/widget/ColorUser.java b/app/src/main/java/com/bjca/hp/acupuncture/widget/ColorUser.java
new file mode 100644
index 0000000..89d826e
--- /dev/null
+++ b/app/src/main/java/com/bjca/hp/acupuncture/widget/ColorUser.java
@@ -0,0 +1,22 @@
+package com.bjca.hp.acupuncture.widget;
+
+import androidx.annotation.ColorInt;
+
+/***************************************************************************
+ * 

+ * @文件名称: ColorUser
+ * @包 路   径:  com.bjca.hp.acupuncture.widget
+ * @版权所有:北京数字医信责任有限公司 (C) 2022
+ *
+ * @类描述:
+ * @版本: V1.0
+ * @创建人: xuqm
+ * @创建时间:2022/1/19 上午 10:58
+ * @修改记录:
+ */
+public class ColorUser {
+    @ColorInt
+    public static final int ce = 0xFF04E8EE;
+    @ColorInt
+    public static final int cs = 0x003A6FF2;
+}
diff --git a/app/src/main/res/drawable/bg_item_welcome.xml b/app/src/main/res/drawable/bg_item_welcome.xml
new file mode 100644
index 0000000..d77a084
--- /dev/null
+++ b/app/src/main/res/drawable/bg_item_welcome.xml
@@ -0,0 +1,11 @@
+
+
+    
+        
+            
+            
+            
+        
+
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_main.xml b/app/src/main/res/drawable/bg_main.xml
new file mode 100644
index 0000000..c34f00b
--- /dev/null
+++ b/app/src/main/res/drawable/bg_main.xml
@@ -0,0 +1,10 @@
+
+
+    
+        
+            
+            
+        
+
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_main_btn.xml b/app/src/main/res/drawable/bg_main_btn.xml
new file mode 100644
index 0000000..fbbb1d9
--- /dev/null
+++ b/app/src/main/res/drawable/bg_main_btn.xml
@@ -0,0 +1,10 @@
+
+
+    
+        
+            
+            
+        
+
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_main_item_content.xml b/app/src/main/res/drawable/bg_main_item_content.xml
new file mode 100644
index 0000000..9fe71d4
--- /dev/null
+++ b/app/src/main/res/drawable/bg_main_item_content.xml
@@ -0,0 +1,10 @@
+
+
+    
+        
+            
+            
+        
+
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_main_item_index.xml b/app/src/main/res/drawable/bg_main_item_index.xml
new file mode 100644
index 0000000..e075c4a
--- /dev/null
+++ b/app/src/main/res/drawable/bg_main_item_index.xml
@@ -0,0 +1,10 @@
+
+
+    
+        
+            
+            
+        
+
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_main_tag.xml b/app/src/main/res/drawable/bg_main_tag.xml
new file mode 100644
index 0000000..01e02eb
--- /dev/null
+++ b/app/src/main/res/drawable/bg_main_tag.xml
@@ -0,0 +1,10 @@
+
+
+    
+        
+            
+            
+        
+
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..437d3e6
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,698 @@
+
+
+
+    
+
+        
+
+        
+
+            
+
+                
+
+                
+
+            
+
+            
+
+                
+
+                    
+
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+                
+
+                
+
+                    
+
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+
+                
+
+                
+
+                    
+
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+
+                    
+
+                
+
+            
+
+            
+
+
+                
+
+                
+            
+
+            
+
+            
+
+
+                
+
+                
+            
+
+            
+
+                
+
+                    
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+                
+
+                
+
+                    
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+                
+
+                
+
+                    
+
+                        
+
+                        
+                    
+
+                    
+
+                        
+
+                        
+                    
+                
+
+
+
+            
+
+            
+        
+
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml
new file mode 100644
index 0000000..1b94db6
--- /dev/null
+++ b/app/src/main/res/layout/activity_setting.xml
@@ -0,0 +1,167 @@
+
+
+
+    
+
+        
+
+        
+
+            
+
+            
+
+            
+
+        
+
+        
+
+        
+
+            
+
+            
+
+            
+
+            
+
+        
+
+        
+
+        
+
+
+            
+
+            
+
+            
+
+        
+
+    
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_test.xml b/app/src/main/res/layout/activity_test.xml
new file mode 100644
index 0000000..20e69cd
--- /dev/null
+++ b/app/src/main/res/layout/activity_test.xml
@@ -0,0 +1,30 @@
+
+
+
+    
+
+        
+
+