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.ICHSubscribeClient; 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.LoggingUtils; import com.emato.ich.utils.ResourceUtils; 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.provider.SyncStateContract; 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 com.xuexiang.xupdate.aria.AriaDownloadServiceProxyImpl; import com.xuexiang.xupdate.aria.AriaDownloader; import com.xuexiang.xupdate.easy.EasyUpdate; import com.xuexiang.xupdate.easy.config.UpdateConfig; import com.xuexiang.xupdate.entity.UpdateEntity; import com.xuexiang.xupdate.proxy.impl.DefaultUpdateParser; 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(); ICHSubscribeClient ichSubscribeClient = ICHSubscribeClient.getInstance(); ICHTopic.CLIENT_ID = BaseUtils.getClientId(); // 订阅主题 // ICHSubscribeClient ichSubscribeClient = ICHSubscribeClient.getInstance(); openLocker(ichSubscribeClient, ichPublishClient); // 注册柜子信息 cabinetInfoReport(ichPublishClient); // TODO 更新版本监听 autoUpdateVersion(ichSubscribeClient); // TODO 监听shell命令脚本 executeShell(ichSubscribeClient, 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); LoggingUtils.sendErrorLog("业务异常: 获取系统配置错误! 网络错误! ", e); } @Override public void onResponse (@NotNull Call call, @NotNull Response response) throws IOException { try { 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)); } 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(ICHSubscribeClient ichSubscribeClient) { ichSubscribeClient.subscribe(String.format(ICHTopic.APK_UPDATE_PATH, BaseUtils.getClientId()), (msgId, msg) -> { try { // String path = new String(msg.getPayload()); // 发起请求下载APK Log.i(TAG, "autoUpdateVersion: =====================>接收到服务器发来更新指令! 开始更新! "); UpdateConfig updateConfig = EasyUpdate.getUpdateConfig(getApplication()); EasyUpdate.create(getBaseContext(), ICSPApi.GET_UPDATE_PATH.getUrl()) .updateHttpService(AriaDownloader.getUpdateHttpService(getApplication())) .build() .update(); // 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); LoggingUtils.sendErrorLog("业务异常: 更新版本监听失败! ", e); } }); } private UpdateEntity getUpdateEntityFromAssets() { // UpdateEntity updateEntity = new UpdateEntity(); // updateEntity.setVersionCode(3); // // return new DefaultUpdateParser().parseJson(ResourceUtils.readStringFromAssert("update_test.json", getAssets())); } private void executeShell(ICHSubscribeClient ichSubscribeClient, ICHPublishClient ichPublishClient){ ichSubscribeClient.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) { Log.i(TAG, "executeShell: =====================>接到服务端传来命令: " + shellVo.getScript() + ", 参数: " + shellVo.getArgs()); BaseUtils.executeShell(shellVo); } else { Log.i(TAG, "executeShell: =====================>接到服务端传来空命令, 不执行! "); 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); Log.i(TAG, "executeShell: =====================>发送命令执行结果成功! "); } catch (Exception e) { Log.e(TAG, "onCreate: 发送执行脚本结果失败! ", e); LoggingUtils.sendErrorLog("业务异常: 发送执行脚本结果失败! ", e); } } }); } private void openLocker(ICHSubscribeClient ichSubscribeClient, ICHPublishClient ichPublishClient) { ichSubscribeClient.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); Log.i(TAG, "openLocker: ==================>接到开锁消息: " + 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); Log.i(TAG, "openLocker: ==================>发送开锁失败消息成功! 锁板id: " + message.getSection() + ", 端口: " + message.getPort()); } catch (JsonProcessingException e) { Log.e(TAG, "onCreate: ---------------------序列化开锁错误消息失败! ", e); LoggingUtils.sendErrorLog("业务异常: 序列化开锁错误消息失败! ", e); } catch (Exception e) { Log.e(TAG, "onCreate: ---------------------未知错误! ", e); LoggingUtils.sendErrorLog("业务异常: 序列化开锁未知错误! ", e); } } else { // TODO 暂时不做 成功需要不断去请求查询锁是否关闭, 关闭后推送成功消息 // 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 { Log.i(TAG, "onCreate: =====================>开锁成功! 锁板id: " + message.getSection() + ", 端口: " + message.getPort()); 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); LoggingUtils.sendErrorLog("业务异常: 序列化开锁成功消息失败! ", e); } catch (RuntimeException e) { Log.e(TAG, "onCreate: ---------------------序列化开锁成功消息未知错误! ", e); LoggingUtils.sendErrorLog("业务异常: 开锁未知错误! ", 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("unknown"); cabinet.setPlatType("S905"); cabinet.setSim("unknown"); cabinet.setWifiSSid("unknown"); 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); Log.i(TAG, "cabinetInfoReport: ===============>上报柜子信息成功! "); } catch (JsonProcessingException e) { Log.e(TAG, "onCreate: 解析成JSON失败!", e); LoggingUtils.sendErrorLog("业务异常: 上报柜子信息时解析成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; } }