package com.emato.ich; import android.os.Bundle; import com.cherry.sdk.controller.utils.ScanGunKeyEventHelper; import com.emato.ich.api.ICSPApi; import com.emato.ich.api.ICSPClient; import com.emato.ich.api.ICSPResponseCodeEnum; import com.emato.ich.contant.SystemConfigConstant; import com.emato.ich.crash.CrashApplication; import com.emato.ich.device.DeviceControl; import com.emato.ich.entity.Cabinet; import com.emato.ich.entity.Message; import com.emato.ich.entity.vo.ResponseData; import com.emato.ich.entity.vo.ShellVo; import com.emato.ich.local.LocalStorage; import com.emato.ich.message.ICHPublishClient; import com.emato.ich.message.ICHTopic; import com.emato.ich.update.APKUpdateDownload; import com.emato.ich.update.OnDownloadListener; import com.emato.ich.utils.BaseUtils; import com.emato.ich.utils.JacksonUtils; import com.emato.ich.utils.StringUtils; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import androidx.appcompat.app.AppCompatActivity; import android.util.Log; import android.view.KeyEvent; import androidx.navigation.NavController; import androidx.navigation.Navigation; import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.NavigationUI; import com.emato.ich.databinding.ActivityMainBinding; import com.xuexiang.xupdate.XUpdate; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import okhttp3.Call; import okhttp3.Callback; import okhttp3.Response; public class MainActivity extends AppCompatActivity { private AppBarConfiguration appBarConfiguration; private ActivityMainBinding binding; public ScanGunKeyEventHelper scanGunKeyEventHelper; private final Map bundleMap = new ConcurrentHashMap<>(); private final Map configMap = new ConcurrentHashMap<>(); private static final String TAG = MainActivity.class.getName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityMainBinding.inflate(getLayoutInflater()); // 强制关闭输入法 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); setContentView(binding.getRoot()); // 自动重启 ((CrashApplication) getApplication()).addActivity(MainActivity.this); // 获取系统配置 getSystemConfig(); ICHPublishClient ichPublishClient = ICHPublishClient.getInstance(); ICHTopic.CLIENT_ID = BaseUtils.getClientId(); // 订阅主题 // ICHSubscribeClient ichSubscribeClient = ICHSubscribeClient.getInstance(); openLocker(ichPublishClient); // 注册柜子信息 cabinetInfoReport(ichPublishClient); // TODO 更新版本监听 autoUpdateVersion(ichPublishClient); // TODO 监听shell命令脚本 executeShell(ichPublishClient); } private void getSystemConfig(){ ICSPClient.getSystemConfig("", BaseUtils.getClientId(), new Callback() { @Override public void onFailure(@NotNull Call call, @NotNull IOException e) { Log.e(TAG, "onFailure: 获取系统配置错误! 网络错误! ", e); } @Override public void onResponse (@NotNull Call call, @NotNull Response response) throws IOException { try { OnDownloadListener listener = new OnDownloadListener() { @Override public void onDownloadSuccess(File file) { } @Override public void onDownloading(int progress) { } @Override public void onDownloadFailed(Exception e) { } }; String parseResponse = ICSPClient.isSuccessfulAndParseResponse(response); ObjectMapper objectMapper = JacksonUtils.objectmapper; ResponseData> readValue = objectMapper.readValue(parseResponse, new TypeReference>>() { }); if (null != readValue && readValue.getCode().equals(ICSPResponseCodeEnum.OK.getCode())) { configMap.putAll(readValue.getData()); // 系统配置的session过期时间 String time = configMap.get(SystemConfigConstant.deliverer_token_expire_seconds); if (!StringUtils.isNullOrEmpty(time)) { LocalStorage.getInstance().getSession().setTime(Long.parseLong(time)); } String qrcode_url = configMap.get(SystemConfigConstant.cabinet_take_object_qrcode_url); try { ICSPClient.download(qrcode_url, new Callback() { @Override public void onFailure(@NotNull Call call, @NotNull IOException e) { } @Override public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { InputStream is = null; byte[] buf = new byte[2048]; int len = 0; FileOutputStream fos = null; final String destFileDir = "res/drawable/"; String destFileName = "e_mp_qrcode_8x8.jpg"; //储存下载文件的目录 File dir = new File(getApplication().getFilesDir().getAbsolutePath() + "/" +destFileDir); if (!dir.exists()) { dir.mkdirs(); } // destFileName = apk_url.substring(apk_url.lastIndexOf('/'), apk_url.length() - 1); File file = new File(dir, destFileName); try { is = response.body().byteStream(); long total = response.body().contentLength(); fos = new FileOutputStream(file); long sum = 0; while ((len = is.read(buf)) != -1) { fos.write(buf, 0, len); sum += len; int progress = (int) (sum * 1.0f / total * 100); //下载中更新进度条 listener.onDownloading(progress); } fos.flush(); //下载完成 listener.onDownloadSuccess(file); } catch (Exception e) { listener.onDownloadFailed(e); }finally { try { if (is != null) { is.close(); } if (fos != null) { fos.close(); } } catch (IOException e) { } } } }, listener); } catch (Exception e) { } Log.i(TAG, "onResponse: 获取系统配置成功! "); } else { Log.w(TAG, "onResponse: code==>" + readValue.getCode() + ", msg==>" + readValue.getMsg()); } } catch (RuntimeException e) { Log.e(TAG, "onResponse: 获取系统配置错误! 未知错误! ", e); } } }); } private void autoUpdateVersion(ICHPublishClient ichPublishClient) { ichPublishClient.subscribe(String.format(ICHTopic.APK_UPDATE_PATH, BaseUtils.getClientId()), (msgId, msg) -> { try { // String path = new String(msg.getPayload()); // 发起请求下载APK XUpdate.newBuild(this) .updateUrl(ICSPApi.GET_UPDATE_PATH.getUrl()) .isAutoMode(true) // 如果需要完全无人干预,自动更新,需要root权限【静默安装需要】 .update(); Log.i(TAG, "autoUpdateVersion: ====================================>更新完成! "); // APKUpdateDownload.getInstance().downloadAPK(MainActivity.this, getApplication(), path); } catch (Exception e) { Log.e(TAG, "onCreate: 更新版本监听失败! ", e); } }); } private void executeShell(ICHPublishClient ichPublishClient){ ichPublishClient.subscribe(String.format(ICHTopic.EXECUTE_SHELL_SCRIPT, BaseUtils.getClientId()), (msgId, msg) -> { if (msg != null) { try { ShellVo shellVo = JacksonUtils.objectmapper.readValue(msg.getPayload(), ShellVo.class); ShellVo result = shellVo; if (shellVo != null && shellVo.getScript() != null && "".equals(shellVo.getScript()) && shellVo.getScript().length() > 0) { BaseUtils.executeShell(shellVo); } else { result = new ShellVo(); result.setResult("命令为空, 不可执行!"); } MqttMessage mqttMessage = new MqttMessage(); mqttMessage.setQos(1); mqttMessage.setPayload(JacksonUtils.objectmapper.writeValueAsString(result).getBytes()); ichPublishClient.publish(String.format(ICHTopic.EXECUTE_SHELL_SCRIPT_RESPONSE, BaseUtils.getClientId()), mqttMessage); } catch (Exception e) { Log.e(TAG, "onCreate: 发送执行脚本结果失败! ", e); } } }); } private void openLocker(ICHPublishClient ichPublishClient) { ichPublishClient.subscribe(ICHTopic.LOCK + BaseUtils.getClientId(), (s, msg) -> { String payload = new String(msg.getPayload()); ObjectMapper objectMapper = JacksonUtils.objectmapper; Message message = objectMapper.readValue(payload, Message.class); Log.i(TAG, "onCreate: message id: " + s + "--------------消息体: " + message); DeviceControl.unlockLocker(message.getSection(), message.getPort(), (var1, var2) -> { Log.i(TAG, "onCreate: 开锁返回码: " + var1 + "--------------返回消息: " + Arrays.asList(var2)); MqttMessage mqttMessage; if (var1 != 0) { try { mqttMessage = wrapMessage(message, objectMapper); ichPublishClient.publish(String.format(ICHTopic.CALLBACK_FAILED, BaseUtils.getClientId()), mqttMessage); } catch (JsonProcessingException e) { Log.e(TAG, "onCreate: ---------------------序列化开锁错误消息失败! ", e); } catch (Exception e) { Log.e(TAG, "onCreate: ---------------------未知错误! ", e); } } else { // TODO 暂时不做 成功需要不断去请求查询锁是否关闭, 关闭后推送成功消息 Log.i(TAG, "onCreate: -------------------------开锁成功"); // AtomicBoolean atomicBoolean = new AtomicBoolean(true); // AtomicInteger atomicInteger = new AtomicInteger(5); // do { // try { // TimeUnit.SECONDS.sleep(30); // } catch (InterruptedException e) { // Log.e(TAG, "onCreate: 等待查询锁状态时线程中断! ", e); // } // DeviceControl.queryLocker(message.getSection(), message.getPort(), (var3, var4) -> { // List strings = Arrays.asList(var4); // if (var3 == 0 && strings.size() > 0 && !strings.get(0).equals("locked")) { // atomicBoolean.set(false); // } // atomicInteger.decrementAndGet(); // }); // if (atomicInteger.get() <= 0) { // atomicBoolean.set(false); // } // } while(atomicBoolean.get()); try { mqttMessage = wrapMessage(message, objectMapper); // if (atomicInteger.get() <= 0) { // message.setCause("长时间未关闭柜门!"); // mqttMessage.setPayload(objectMapper.writeValueAsBytes(message)); // ichPublishClient.publish(String.format(ICHTopic.CALLBACK_FAILED, BaseUtils.getClientId()), mqttMessage); // } ichPublishClient.publish(String.format(ICHTopic.CALLBACK_SUCCESS, BaseUtils.getClientId()), mqttMessage); } catch (JsonProcessingException e) { Log.e(TAG, "onCreate: ---------------------序列化开锁成功消息失败! ", e); } catch (RuntimeException e) { Log.e(TAG, "onCreate: ---------------------未知错误! ", e); } } }); }); } private void cabinetInfoReport(ICHPublishClient ichPublishClient){ String appVersion = BaseUtils.getAppVersion(getApplicationContext()); String androidVersion = BaseUtils.getVersionName(); CountDownLatch countDownLatch = new CountDownLatch(10); Cabinet cabinet = DeviceControl.queryCabinetInfo(countDownLatch); try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } cabinet.setClientId(BaseUtils.getClientId()); cabinet.setSoftwareVersion(appVersion); cabinet.setAndroidVersion(androidVersion); cabinet.setSoftwareType("android"); cabinet.setImei(BaseUtils.getIMEI(getApplicationContext())); cabinet.setMacIpv4(BaseUtils.getIp()); cabinet.setMacIpv6("unknown"); cabinet.setNetType("111"); cabinet.setPlatType("S905"); cabinet.setSim("111"); cabinet.setWifiSSid("111"); ObjectMapper objectMapper = JacksonUtils.objectmapper; try { String jsonData = objectMapper.writeValueAsString(cabinet); Log.i(TAG, "onCreate: jsonData===============>" + jsonData); MqttMessage message = new MqttMessage(); message.setQos(1); message.setPayload(jsonData.getBytes()); ichPublishClient.publish(String.format(ICHTopic.CABINET_INFO_REPORT, BaseUtils.getClientId()), message); } catch (JsonProcessingException e) { Log.e(TAG, "onCreate: 解析成JSON失败!", e); } } @Override public boolean dispatchKeyEvent(KeyEvent event) { if (null != scanGunKeyEventHelper) { scanGunKeyEventHelper.analysisKeyEvent(event); } return true; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. // getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. // int id = item.getItemId(); // //noinspection SimplifiableIfStatement // if (id == R.id.action_settings) { // return true; // } return super.onOptionsItemSelected(item); } @Override public boolean onSupportNavigateUp() { NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp(); } private MqttMessage wrapMessage(Message message, ObjectMapper objectMapper) throws JsonProcessingException { MqttMessage mqttMessage = new MqttMessage(); Message failedMsg = new Message(); // TODO 失败原因枚举 failedMsg.setCause("失败原因枚举"); failedMsg.setMessageId(message.getMessageId()); failedMsg.setClientId(message.getClientId()); failedMsg.setCmd(message.getCmd()); failedMsg.setDatetime(message.getDatetime()); failedMsg.setPort(message.getPort()); failedMsg.setScene(message.getScene()); failedMsg.setSection(message.getSection()); mqttMessage.setQos(1); mqttMessage.setPayload(objectMapper.writeValueAsBytes(failedMsg)); return mqttMessage; } public Map getBundleMap() { return bundleMap; } public Map getConfigMap() { return configMap; } }