# SerialPortReadme **Repository Path**: niekang001/serial-port-readme ## Basic Information - **Project Name**: SerialPortReadme - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-06-21 - **Last Updated**: 2021-06-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 串口操作演示demo > [引用与参考的库](https://github.com/licheedev/SerialWorker) > 主要用来演示对接btb咖啡机的各种操作 > > 也封装好了相应的api供调用,不用在写串口指令的发送和接收,数据解析什么的 > > 还放了个串口调试工具和发送几个简单的固定命令,方便你自己测试命令优化代码什么的 --- # 我的运行环境 > Android Studio 4.1.3 > > targetSdkVersion 30 > > minSdkVersion 19 > > [gradle-wrapper.properties内] gradle-6.5-all > > [根目录下的build.gradle] gradle 3.4.2 > > 测试设备:android 7.0 ,瑞芯微rk3288, 厂家:视美泰 --- # 如何使用它 ## Step 1.先点击file→new→import module,选择demo项目中的btb_serialport目录来导入到你的项目 ``` 导入后如果出现错误,请参考自己的build.gradle,对module中的build.gradle进行修改,例如:androidx,修改compileSdkVersion,buildToolsVersion,添加include等等 ``` ## Step 2.然后在 build.gradle(Module:app或其它需操作串口的module) 的 dependencies 添加: ``` dependencies { implementation project(':btb_serialport') } ``` ## Step 3.在需要使用到和释放掉的地方加入启动服务和停止服务的代码 ``` @Override protected void onCreate(Bundle savedInstanceState) { if (mServiceDelegate == null) { mServiceDelegate = new CommServiceDelegate(this); mServiceDelegate.connectService(true, true); } } ``` ``` @Override protected void onDestroy() { if (mServiceDelegate != null) { mServiceDelegate.unbindCommService(); CommServiceDelegate.killService(); mServiceDelegate = null; } } ``` > 注意服务不能多次开启和多次关闭,所以考虑到多activity跳转的场景的生命周期,需要启动和关闭的地方可能不一样 > > 这时候可以在MainActivity中启动一次服务(MainActivity跳转时不会手动finish的情况下),退出app之前释放掉,这部分请自行实现 > > 如果启动新Activity前都会手动finish旧Activity,请参考上面的写法在每个activity的oncreate和ondestroy中手动开启和关闭服务或用其它方法来实现 ## Step 4.发送各种命令与相应的回调 ``` 请参考demo的写法,使用前记得服务要先启动 ``` # API方法说明 > 供调用的方法基本放在SerialManager.java 内 > api提供回调,但是也有部分回调通过eventbus来回传(如机器整体状态信息,需手动确认的故障信息),code与说明可以查看module中的EventCode.java内 > > 注意设置的自动发送时间间隔一定要比超时时间长,否则通信故障情况下可能会造成发送队列越发越长,建议发送间隔500~1000ms,超时时间300~500ms ``` checkState : 发送获取当前机器状态的命令(需要一直发送获取到机器的最新的状态,SerialManager有开启自动发送的代码,回调通过eventbus来获取) setShutDown : 关机流程(会先清洗后再关机) setMakeDrink : 发送制作饮品的命令(饮品参数见bean包) setSettingCommand : 发送机器参数设置的命令 checkSettingCommand : 获取机器参数的命令 setConfirmCommand : 发送确定/取消的命令(取消命令如取消饮品制作,确认命令如某些需要手动确认的故障,提示用户按操作完成后再点确认的时候发送这个) setMaintenance : 发送维护/清洗的命令(参数见bean包) ``` ``` bean类和解析包 MachineStateBean : 用于接收机器状态,包括故障状态,工作状况等 MakeDrinkBean : 用于发送/发送中修改饮品参数,参数说明见注释 SettingBean : 用于发送机器设置,参数说明见注释 bean类与串口指令的转换见recv包与send包 recv类,将串口返回的命令解析为bean类 send类,将传过来的bean类转为发送给串口的命令 ``` > 调用示例 ``` //这里是一个制作饮品的示例 //先将饮品的参数set进bean类 MakeDrinkBean bean = new MakeDrinkBean(); //咖啡粉量 bean.setCoffeePowderAmount(Integer.parseInt(tvCofferPowderAmount.getText().toString().trim())); //饮品类别(固定了十几种饮品) bean.setDrinkType(cofferTypePosition); //饮品咖啡量 bean.setCoffeeAmount(avCofferAmount.getAmount()); //饮品热水量 bean.setHotWaterAmount(avHotWaterAmount.getAmount()); //饮品奶量 bean.setMilkAmount(avMilkAmount.getAmount()); //饮品奶沫量 bean.setMilkFoamAmount(avMilkFoamAmount.getAmount()); //将饮品的bean类new给转化类 SendMakeDrink command = new SendMakeDrink(bean); //发送串口命令并回调 SerialManager.get().setMakeDrink(command, new Callback() { @Override public void onSuccess(RecvMakeDrink command) { //超时前获取到正确的命令会在这里回调 LogPlus.i("result=" + command.toString()); if (command.isResult()) { Constant.nowMakeDrink = bean; ToastUtil.showToast("执行成功"); } else { ToastUtil.showToast("执行失败"); } } @Override public void onFailure(Throwable tr) { //如果出现错误或超时没获取到正确的回调会在这里报错 LogPlus.e("onError", tr); ToastUtil.showToast(tr.getMessage()); } }); ``` > 开启了定时获取状态的情况下,使用eventbus获取最新状态的回调的示例 ``` @Subscribe(threadMode = ThreadMode.MAIN) public void onReceiveEvent(EventMessage event) { if (EventCode.EVENT_MACHINE_STATE == event.getCode()) { RecvStateReadTemp recvStateReadTemp = (RecvStateReadTemp) event.getData(); LogPlus.e("result=" + recvStateReadTemp.toString()); updateSerialPortState(recvStateReadTemp); } } //主要是介绍各个参数的意思 private void updateSerialPortState(RecvStateReadTemp command) { if (command.getBean() == null) { return; } if (command.getBean().isMakingDrink() && popupView != null) { if (!popupView.isDismiss()) { popupView.setProgress((int) (command.getBean().getProgress() * 100)); String text = "当前工作名称:" + command.getBean().getWorkName() + ",当前状态:"; if (command.getBean().getWorkState() == 0) { text = text + "制作中"; } else if (command.getBean().getWorkState() == 1) { text = text + "制作完成"; } else if (command.getBean().getWorkState() == 2) { text = text + "正在取消制作"; } if (command.getBean().getMakeDrinkState() == 1) { text = text + ",正在制作咖啡,进度:" + (int) (command.getBean().getCofferProgress() * 100) + "%"; } else if (command.getBean().getMakeDrinkState() == 2) { text = text + ",正在制作热水,进度:" + (int) (command.getBean().getHotWaterProgress() * 100) + "%"; } else if (command.getBean().getMakeDrinkState() == 3) { text = text + ",正在制作牛奶,进度:" + (int) (command.getBean().getMilkProgress() * 100) + "%"; } else if (command.getBean().getMakeDrinkState() == 4) { text = text + ",正在制作奶沫,进度:" + (int) (command.getBean().getMilkFoamProgress() * 100) + "%"; } else if (command.getBean().getMakeDrinkState() == 5) { text = text + ",正在磨豆,进度:" + (int) (command.getBean().getGrindingBeansProgress() * 100) + "%"; } popupView.setTvProgressText(text); } } else if (!command.getBean().isMakingDrink() && popupView != null) { if (!popupView.isDismiss()) { popupView.setTvProgressText(""); popupView.setProgress(0); } } if (command.getBean().getWorkState() == 1 || command.getBean().getWorkState() == 2) { Constant.nowMakeDrink = null; } tvError.setText("是否故障:" + command.getBean().isError()); tvState.setText("机器运行状态:" + command.getBean().getState()); tvNeedCleanCore.setText("酿造核心是否需要药片清洗:" + command.getBean().isNeedCleanCore()); tvNeedDescaling.setText("是否需要除垢:" + command.getBean().isNeedDescaling()); tvNeedCleanCream.setText("奶沫系统是否需要清洗:" + command.getBean().isNeedCleanCream()); tvCommunicationError.setText("是否通信异常:" + command.getBean().isCommunicationError()); tvCoffeeBoilerError.setText("是否咖啡锅炉断线:" + command.getBean().isCoffeeBoilerError()); tvSteamBoilerError.setText("是否蒸汽锅炉断线:" + command.getBean().isSteamBoilerError()); tvNTCError.setText("是否NTC异常:" + command.getBean().isNTCError()); tvTransmissionError.setText("是否传动系统异常:" + command.getBean().isTransmissionError()); tvGrindingBeansError.setText("是否磨豆系统异常:" + command.getBean().isGrindingBeansError()); tvPipelineJamError.setText("是否管路堵塞:" + command.getBean().isPipelineJamError()); tvCoffeeBeansEmpty.setText("是否咖啡豆用尽:" + command.getBean().isCoffeeBeansEmpty()); tvTemperatureTooLow.setText("是否温度过低:" + command.getBean().isTemperatureTooLow()); tvTemperatureTooHigh.setText("是否温度过高:" + command.getBean().isTemperatureTooHigh()); tvNeedCore.setText("是否请装入酿造核心:" + command.getBean().isNeedCore()); tvNeedCloseDoor.setText("是否请关闭酿造门:" + command.getBean().isNeedCloseDoor()); tvNeedWasteWaterDisc.setText("是否请装入废水盘:" + command.getBean().isNeedWasteWaterDisc()); tvNeedWasteResidueBox.setText("是否请装入废渣盒:" + command.getBean().isNeedWasteResidueBox()); tvNeedMilkFoamMachine.setText("是否请装入奶沫器:" + command.getBean().isNeedMilkFoamMachine()); tvBoxLackWater.setText("是否水箱缺水:" + command.getBean().isBoxLackWater()); tvFullWasteWater.setText("是否废水满了:" + command.getBean().isFullWasteWater()); tvNeedWaterMouth.setText("是否请装入奶沫器2:" + command.getBean().isNeedMilkFoamMachine2()); tvNeedBeanBox.setText("是否管路堵塞2:" + command.getBean().isPipelineJamError2()); tvPositionValveError.setText("是否高水位检测故障:" + command.getBean().isHighWaterError()); tvFullCoffeeGrounds.setText("是否咖啡渣满:" + command.getBean().isFullCoffeeGrounds()); tvTransmissionPlug.setText("是否传动堵转:" + command.getBean().isTransmissionPlug()); tvWorkState.setText("当前自检状态/制作状态:" + command.getBean().getWorkState()); tvWorkName.setText("制作中的饮品名称/清洗工程名称:" + command.getBean().getWorkName()); tvProgress.setText("制作/清洗进度:" + (command.getBean().getProgress() * 100) + "%"); tvCoffeeBoilerTemperature.setText("咖啡锅炉温度:" + command.getBean().getCoffeeBoilerTemperature()); tvSteamBoilerTemperature.setText("蒸汽锅炉温度:" + command.getBean().getSteamBoilerTemperature()); } ``` # 更新日志 > 后续更新主要是加入api说明,error说明和重试功能等 | VERSION | Description | | :-------: | ------------- | | __0.0.1__ | 封装好了串口module,简单的写了个demo | # 注意事项 ``` 主要module库使用了serialworker和eventbus两个开源库,具体使用方式请参考官方demo自行学习,如你的项目已使用EventBus,请自行统一版本,或在串口module中引用你的基module 主要设置的参数为串口路径(建议配合装机方使用固定串口路径,如需串口轮询的方式来寻找真正串口路径的话请自行实现),串口波特率,串口超时时间都在串口modeul中的Protocol.java和SerialManager.java中,请自行修改 CommServiceDelegate启动后会自动连接串口,无需再手动连接 多moduel的情况下,如果你之前是单module并使用butterknife,需要进行相应的修改来使用R2.id.XX,具体请参考demo中app下的build.gradle和根目录下的build.gradle文件 ``` # Demo介绍 ``` demo使用了以下第三方库,基本都是为了方便演示,实际项目中除了串口module中的serialworker和eventbus,其它全部可以不引用 ``` * [SerialWorker](https://github.com/licheedev/SerialWorker) * [EventBus](https://github.com/greenrobot/EventBus) * [XAOP](https://github.com/xuexiangjys/XAOP) * [XPopup](https://github.com/li-xiaojun/XPopup) * [butterknife](https://github.com/JakeWharton/butterknife)