123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560 |
- package com.bgy.autosale.plc;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import com.bgy.autosale.App;
- import com.bgy.autosale.R;
- import com.bgy.autosale.entitys.DataWrap;
- import com.bgy.autosale.entitys.Result;
- import com.bgy.autosale.interfaces.Callback;
- import com.bgy.autosale.interfaces.SendCallback;
- /**
- * Created by cjx on 2019/9/2
- * 说明:雪糕机PLC通讯协议解析类
- */
- public class IceCreamAgreement extends BasePlcAgreement {
- private static volatile IceCreamAgreement util;
- final int PLC_HEADER = 170; // 头信息
- private final int PLC_ACTION_ORDER = 2; // 下单
- private final int PLC_ACTION_IMMEDIATE = 4;
- private final int PLC_ACTION_CONTROL = 32; //控制设备
- private final int PLC_ACTION_MODIFY = 33; //控制设备
- private final int DELAY_SEND_ORDER = 0; // 延迟发送订单
- private final int DELAY_CHECK_STATUS_MAKE = 1; // 检查是否超时设备未响应
- private boolean makeOrderByManual = false; // 手动下单状态标记
- private Callback<Result<Order>> orderCallback;
- private Callback<Integer> deviceMessageCallback;
- private Callback<int[]> immediateCallback;
- private SendCallback controlCallback; //控制设备
- private int controlKey = -1;
- private SendCallback modifyCallback; //修改参数
- private int modifyKey = -1;
- private int tryCount = 0;
- private Order outOrder;
- private Handler delayHandler;
- private boolean testMode = false;
- private Handler disconnectHandler = new Handler(new Handler.Callback() {
- @Override
- public boolean handleMessage(Message msg) {
- switch (msg.what) {
- case 0:
- disConnect(new Exception(App.app.getString(R.string.plc_disconnect_initiative)));
- disconnectHandler.sendEmptyMessageDelayed(1, 5000);
- break;
- case 1:
- updateOrderErrorMessage(App.app.getString(R.string.plc_disconnect));
- if (statusCallback != null) {
- statusCallback.onResult(getStatusResult(PLC_HEART_DISCONNECT, deviceStatus, null));
- }
- break;
- }
- return false;
- }
- });
- public static IceCreamAgreement getInstance() {
- if (util == null) {
- synchronized (IceCreamAgreement.class) {
- if (util == null) {
- util = new IceCreamAgreement();
- }
- }
- }
- return util;
- }
- IceCreamAgreement() {
- super();
- TAG = App.app.getString(R.string.app_name) + " >> ";
- delayHandler = new Handler(new Handler.Callback() {
- @Override
- public boolean handleMessage(Message msg) {
- if (deviceStatus == null) {
- return false;
- }
- switch (msg.what) {
- case DELAY_SEND_ORDER:
- // 控制模式
- int control = deviceStatus[0];
- // 工作状态
- int work = deviceStatus[1];
- // 设备状态
- int device = deviceStatus[2];
- if (work == PLC_WORK_FREE && control == PLC_CONTROL_AUTO && device == PLC_DEVICE_NORMAL) {
- if (getPrevDataWrap(PLC_ACTION_ORDER) == null) {
- outOrder = (Order) msg.obj;
- sendOrderData();
- } else {
- log.e_s(TAG, App.app.getString(R.string.plc_has_other_order));
- }
- } else {
- tryCount++;
- if (tryCount > 10) {
- return false;
- }
- log.e_s(TAG, App.app.getString(R.string.plc_send_order_again));
- Message newMsg = Message.obtain();
- newMsg.what = DELAY_SEND_ORDER;
- newMsg.obj = msg.obj;
- delayHandler.sendMessageDelayed(newMsg, 2000);
- }
- break;
- case DELAY_CHECK_STATUS_MAKE:
- updateOrderErrorMessage(App.app.getString(R.string.plc_make_error_not_status));
- break;
- }
- return false;
- }
- });
- }
- @Override
- protected int getStatusLength() {
- return 13;
- }
- @Override
- public void onConnectedStatusChange(boolean connected, Exception e, String msg) {
- log.ui(TAG, String.format(App.app.getString(R.string.plc_connect_status), String.valueOf(connected), msg));
- updateConnectStatus();
- if (statusCallback != null) {
- if (connected) {
- statusCallback.onResult(getStatusResult(PLC_HEART_CONNECT, deviceStatus, msg));
- }
- }
- }
- @Override
- protected boolean isTheSame(int size, int[] content) {
- boolean theSame = true;
- // 先对比第13个位的值(复位结果)是否一致
- if (size > 12) {
- if (content[12] != deviceStatus[12]) {
- return false;
- }
- }
- if (size > 7) {
- if (content[7] != deviceStatus[7]) {
- return false;
- }
- }
- // 只对比前7个状态
- int maxSize = Math.min(size, 7);
- for (int i = 0; i < maxSize; i++) {
- if (content[i] != deviceStatus[i]) {
- theSame = false;
- break;
- }
- }
- return theSame;
- }
- @Override
- protected void sendDataFail(int tag) {
- switch (tag) {
- case PLC_ACTION_ORDER:
- updateOrderErrorMessage(App.app.getString(R.string.plc_order_no_response));
- break;
- case PLC_ACTION_MODIFY:
- if (modifyCallback != null) {
- modifyCallback.callBack(false, null);
- }
- break;
- case PLC_ACTION_CONTROL:
- if (controlCallback != null) {
- controlCallback.callBack(false, null);
- }
- break;
- }
- }
- @Override
- protected byte[] checkAction(int action, int random, int[] content) {
- updateConnectStatus();
- final int PLC_ACTION_HEART = 0;
- final int PLC_ACTION_REPORT = 1; // 状态上报回调
- final int PLC_ACTION_STATUS = 3;
- byte[] response = null;
- Log.d(TAG, "checkAction: "+action);
- // 检查命令
- switch (action) {
- case PLC_ACTION_HEART:
- response = parserHeart(content, PLC_ACTION_REPORT, random);
- break;
- case PLC_ACTION_ORDER:
- // 出餐下单结果
- parserOrder(content);
- break;
- case PLC_ACTION_STATUS:
- // 设备状态上报
- response = parserStatus(content, PLC_ACTION_REPORT, random);
- break;
- case PLC_ACTION_IMMEDIATE:
- Log.d(TAG, "checkAction: PLC_ACTION_IMMEDIATE");
- response = parserImmediate(content, random);
- break;
- case PLC_ACTION_CONTROL://解析控制指令
- parserControl(content);
- break;
- case PLC_ACTION_MODIFY://解析修改参数
- parserModify(content);
- break;
- }
- return response;
- }
- @Override
- protected int getHeaderCode() {
- return PLC_HEADER;
- }
- @Override
- protected void dealStatus(int[] content) {
- // 控制模式
- int control = content[0];
- // 工作状态
- int work = content[1];
- // 设备状态
- int device = content[2];
- // 取菜口1 状态
- int door = content[3];
- if (content.length > 7) {
- int deviceMessage = content[7];
- if (deviceMessageCallback != null) {
- deviceMessageCallback.onResult(deviceMessage);
- }
- }
- // 设备不正常了
- // 手动出餐时, 不需要判断设备状态
- if (!makeOrderByManual && !testMode) {
- if (control != PLC_CONTROL_AUTO || device != PLC_DEVICE_NORMAL) {
- if (outOrder != null) {
- if (outOrder.status == RESULT_CODE_ORDER_CHILD_OUT) {
- if (PLC_DOOR_EMPTY == door) {
- updateOrderStatus(RESULT_CODE_ORDER_CHILD_FINISH, String.format(App.app.getString(R.string.plc_order_taked), outOrder));
- outOrder = null;
- updateOrderErrorMessage(App.app.getString(R.string.plc_order_error2));
- }
- } else if (outOrder.status == RESULT_CODE_ORDER_CHILD_PREPARE) {
- updateOrderErrorMessage(App.app.getString(R.string.plc_order_error2));
- } else {
- outOrder = null;
- }
- }
- delayHandler.removeMessages(DELAY_CHECK_STATUS_MAKE);
- return;
- }
- }
- // 如果有待取餐的菜品并且当前取餐口已经空闲,表示餐已被取
- if (outOrder != null) {
- switch (outOrder.status) {
- case RESULT_CODE_ORDER_CHILD_INIT:
- if (PLC_WORK_FREE != work) {
- outOrder.status = RESULT_CODE_ORDER_CHILD_PREPARE;
- updateOrderStatus(RESULT_CODE_ORDER_CHILD_PREPARE, String.format(App.app.getString(R.string.plc_order_making), outOrder));
- delayHandler.removeMessages(DELAY_CHECK_STATUS_MAKE);
- }
- break;
- case RESULT_CODE_ORDER_CHILD_PREPARE:
- if (PLC_DOOR_EMPTY != door) {
- outOrder.status = RESULT_CODE_ORDER_CHILD_OUT;
- updateOrderStatus(RESULT_CODE_ORDER_CHILD_OUT, String.format(App.app.getString(R.string.plc_order_prepare), outOrder));
- }
- break;
- case RESULT_CODE_ORDER_CHILD_OUT:
- if (PLC_DOOR_EMPTY == door) {
- outOrder.status = RESULT_CODE_ORDER_CHILD_FINISH;
- updateOrderStatus(RESULT_CODE_ORDER_CHILD_FINISH, String.format(App.app.getString(R.string.plc_order_taked), outOrder));
- outOrder = null;
- if (PLC_WORK_FREE == work) {
- updateOrderStatus(RESULT_CODE_ORDER_COMPLETE, App.app.getString(R.string.plc_prepare));
- }
- }
- break;
- }
- } else if (PLC_WORK_FREE == work) {
- updateOrderStatus(RESULT_CODE_ORDER_COMPLETE, App.app.getString(R.string.plc_prepare));
- }
- }
- @Override
- protected void clearOrderFormPlc(int type) {
- }
- public void setOrderCallback(Callback<Result<Order>> orderCallback) {
- this.orderCallback = orderCallback;
- }
- public void setDeviceMessageCallback(Callback<Integer> callback) {
- this.deviceMessageCallback = callback;
- }
- public void setImmediateCallbak(Callback<int[]> callback) {
- this.immediateCallback = callback;
- }
- public void sendOrder(Order order) {
- if (order == null) {
- updateOrderErrorMessage(App.app.getString(R.string.plc_not_order));
- return;
- }
- makeOrderByManual = false;
- tryCount = 0;
- Message msg = Message.obtain();
- msg.what = DELAY_SEND_ORDER;
- msg.obj = order;
- delayHandler.sendMessageDelayed(msg, 300);
- }
- // 控制设备
- public void sendControl(int order, SendCallback sendCallback) {
- sendControl(order, 0, 0, 0, sendCallback);
- }
- public void sendControl(int order, int param1, int param2, int param3, SendCallback sendCallback) {
- if (getPrevDataWrap(PLC_ACTION_CONTROL) != null) {
- if (sendCallback != null) {
- sendCallback.callBack(false, null);
- }
- return;
- }
- this.controlKey = order;
- this.controlCallback = sendCallback;
- final int random = getRandom(); // 随机数
- int length = 8;
- final byte[] data = generateData(PLC_HEADER, PLC_ACTION_CONTROL, random, length, order, param1, param2, param3);
- sendData(new DataWrap(random, data), PLC_ACTION_CONTROL);
- }
- // 设置当前手动出单的状态
- public void setMakeOrderByManual(Order order) {
- outOrder = order;
- if (outOrder != null) {
- outOrder.status = RESULT_CODE_ORDER_CHILD_INIT;
- }
- this.makeOrderByManual = order != null;
- }
- // 修改参数
- public void modifyParams(int order, int param, SendCallback sendCallback) {
- if (getPrevDataWrap(PLC_ACTION_MODIFY) != null) {
- sendCallback.callBack(false, null);
- return;
- }
- this.modifyKey = order;
- this.modifyCallback = sendCallback;
- final int random = getRandom(); // 随机数
- int length = 4;
- final byte[] data = generateData(PLC_HEADER, PLC_ACTION_MODIFY, random, length, order, param);
- sendData(new DataWrap(random, data), PLC_ACTION_MODIFY);
- }
- // 解析即时状态上报
- private byte[] parserImmediate(int[] content, int random) {
- if (immediateCallback != null) {
- Log.d(TAG, "parserImmediate1: ");
- immediateCallback.onResult(content);
- }
- Log.d(TAG, "parserImmediate2: ");
- return generateData(getHeaderCode(), PLC_ACTION_IMMEDIATE, random, 0);
- }
- // 解析订单
- private void parserOrder(int[] content) {
- delayHandler.removeMessages(DELAY_SEND_ORDER);
- if (outOrder == null) {
- log.e_s(TAG, App.app.getString(R.string.plc_order_empty));
- return;
- }
- if (content == null || content.length < 1) {
- updateOrderErrorMessage(App.app.getString(R.string.plc_order_result_empty));
- return;
- }
- // 下单结果
- int result = content[0];
- if (result == 1) {
- outOrder.status = RESULT_CODE_ORDER_CHILD_INIT;
- log.e_s(TAG, String.format(App.app.getString(R.string.plc_order_start), outOrder));
- delayHandler.sendEmptyMessageDelayed(DELAY_CHECK_STATUS_MAKE, 8000);
- } else if (result == 3) { // 忙碌状态
- log.e_s(TAG, String.format(App.app.getString(R.string.plc_order_busy), outOrder));
- } else {
- updateOrderErrorMessage(App.app.getString(R.string.plc_order_error));
- outOrder = null;
- }
- }
- // 解析控制指令
- private void parserControl(int[] content) {
- if (content != null && content.length > 0) {
- if (controlCallback != null) {
- if (content[0] == controlKey) {
- controlCallback.callBack(true, content);
- } else {
- controlCallback.callBack(false, content);
- }
- }
- } else {
- if (controlCallback != null) {
- controlCallback.callBack(false, null);
- }
- }
- controlCallback = null;
- }
- // 解析修改参数
- private void parserModify(int[] content) {
- if (content != null && content.length > 0) {
- if (modifyCallback != null) {
- if (content[0] == modifyKey) {
- modifyCallback.callBack(true, content);
- } else {
- modifyCallback.callBack(false, content);
- }
- }
- } else {
- if (modifyCallback != null) {
- modifyCallback.callBack(false, null);
- }
- }
- modifyCallback = null;
- }
- // 发送下单命令
- private void sendOrderData() {
- Order order = outOrder;
- log.e_s(TAG, String.format(App.app.getString(R.string.plc_order_receive), order));
- int random = getRandom();
- int length = 6;
- byte[] data = generateData(PLC_HEADER, PLC_ACTION_ORDER, random, length, order.flavor, order.sauce, order.kernel);
- sendData(new DataWrap(random, data), PLC_ACTION_ORDER);
- }
- // 设备是否正常
- public boolean isNormal() {
- synchronized (IceCreamAgreement.class) {
- return deviceStatus != null && deviceStatus[0] == PLC_CONTROL_AUTO && deviceStatus[2] == PLC_DEVICE_NORMAL;
- }
- }
- public boolean isAuto() {
- return deviceStatus != null && deviceStatus[0] == PLC_CONTROL_AUTO;
- }
- public boolean isDeviceNoErr() {
- return deviceStatus != null && deviceStatus[2] == PLC_DEVICE_NORMAL;
- }
- public boolean isDeviceDoorNoWarn() {
- return deviceStatus != null && deviceStatus[3] == PLC_DOOR_EMPTY;
- }
- public boolean isDeviceFree() {
- return deviceStatus != null && deviceStatus[1] == PLC_WORK_FREE;
- }
- // 设备是否空闲
- public boolean isFree() {
- synchronized (IceCreamAgreement.class) {
- return deviceStatus != null && deviceStatus[1] == PLC_WORK_FREE && deviceStatus[3] == PLC_DOOR_EMPTY;
- }
- }
- public String getStatusString() {
- if (deviceStatus == null) {
- return null;
- }
- StringBuilder stringBuilder = new StringBuilder(4);
- stringBuilder.append(deviceStatus[0])
- .append(deviceStatus[2])
- .append(deviceStatus[1])
- .append(deviceStatus[3]);
- return stringBuilder.toString();
- }
- private void updateOrderErrorMessage(String msg) {
- if (outOrder != null && outOrder.status != RESULT_CODE_ORDER_CHILD_PREPARE) {
- outOrder = null;
- }
- updateOrderStatus(RESULT_CODE_ORDER_ERROR, msg);
- outOrder = null;
- }
- private void updateOrderStatus(int code, String msg) {
- log.e_s(TAG, msg);
- if (orderCallback != null) {
- orderCallback.onResult(new Result<>(code, outOrder, msg));
- }
- }
- private void updateConnectStatus() {
- if (statusCallback != null) {
- statusCallback.onResult(getStatusResult(PLC_HEART_CONNECT, deviceStatus, null));
- }
- disconnectHandler.removeMessages(0);
- disconnectHandler.removeMessages(1);
- disconnectHandler.sendEmptyMessageDelayed(0, 120000);
- }
- public void setTestMode() {
- testMode = true;
- }
- public static class Order {
- public Object tag; // 标记
- int flavor; // 口味 1:原味
- int sauce; // 酱料 0:无口味,1:菠萝,2:草莓酱,3:蓝莓,
- int kernel; // 果仁 0:无口味,1:花生碎,2:榛子碎,3:腰果碎
- int status; // 出餐状态
- public Order(Object tag, int flavor, int sauce, int kernel) {
- this.tag = tag;
- this.flavor = flavor;
- this.sauce = sauce;
- this.kernel = kernel;
- this.status = -1;
- }
- @Override
- public String toString() {
- return "{" +
- "flavor:" + flavor +
- ", sauce:" + sauce +
- ", kernel:" + kernel +
- ", status:" + status +
- '}';
- }
- }
- }
|