/**
   * DLMS升级第三步 传输升级包文件,客户端按照Step 1中获取的imageBlockSize分帧传送升级包文件,升级包的传输通过action操作image
   * transfer对象的方法2完成;
   *
   * @param req
   * @param dr
   */
  private boolean upgradeStep_03(DlmsRequest req, DlmsRequest dr) {

    if (req.getParams()[0].resultCode != 0) return false;

    dr.setOperator(DlmsUpgradeAssisant.UPGRADE_03);
    dr.setOpType(DLMS_OP_TYPE.OP_ACTION);
    int i_maxSize = (Integer) dr.getAppendParam(DlmsUpgradeAssisant.MAX_SIZE);
    byte[] content = (byte[]) dr.getAppendParam(DlmsUpgradeAssisant.UPGRADE_CONTENT);
    int currentBlockNum = 0;
    if (!dr.containsKey(DlmsUpgradeAssisant.CURRENT_BLOCK_NUM)) currentBlockNum = 0;
    else currentBlockNum = (Integer) dr.getAppendParam(DlmsUpgradeAssisant.CURRENT_BLOCK_NUM) + 1;
    dr.addAppendParam(DlmsUpgradeAssisant.CURRENT_BLOCK_NUM, currentBlockNum);
    if (tracer.isEnabled()) {
      tracer.trace(
          "MeterId:"
              + dr.getMeterId()
              + ",BlockCount:"
              + (Integer) dr.getAppendParam(DlmsUpgradeAssisant.BLOCK_COUNT)
              + ",CurrentBlockNum:"
              + currentBlockNum);
    }

    if (currentBlockNum == (Integer) dr.getAppendParam(DlmsUpgradeAssisant.BLOCK_COUNT)
        || (content.length % i_maxSize == 0
            && currentBlockNum + 1
                == (Integer) dr.getAppendParam(DlmsUpgradeAssisant.BLOCK_COUNT))) {
      // 当前发送是最后一帧
      dr.addAppendParam(DlmsUpgradeAssisant.IS_TRANSFER_FINISHED, true);
    }
    byte[] currentSendBlock = getCurUpgradeBlock(content, currentBlockNum, i_maxSize);
    String logicAddr = req.getMeterId();
    int tn = 0;
    if (req.getRelayParam() != null) {
      logicAddr = req.getRelayParam().getDcLogicalAddress();
      tn = req.getRelayParam().getMeasurePoint();
    }
    if (tracer.isEnabled())
      tracer.trace(
          "meterId:"
              + logicAddr
              + ",tn:"
              + tn
              + ",currentBlockNum:"
              + currentBlockNum
              + ",blockContent:"
              + HexDump.toHex(currentSendBlock));
    blockTransferRequest(dr, currentBlockNum, currentSendBlock);
    return true;
  }
 public byte[] fileHeadConstruct(DlmsRequest req) {
   String strFileHead = (String) req.getAppendParam(DlmsUpgradeAssisant.FILE_HEAD);
   if (tracer.isEnabled()) tracer.trace("MeterId:" + req.getMeterId() + "FileHead:" + strFileHead);
   byte[] fileHead = HexDump.toArray(strFileHead);
   if (fileHead[1] == 1) { // 加密
     ByteBuffer iv = ByteBuffer.allocate(12);
     DlmsContext context = contextManager.getContext(req.getMeterId());
     byte[] verfication = new byte[16];
     try {
       System.arraycopy(fileHead, 23, verfication, 0, 16);
       byte[] encryptVerfiy = AESGcm128.encrypt(context.encryptKey, iv.array(), verfication, null);
       System.arraycopy(encryptVerfiy, 0, fileHead, 23, 16);
     } catch (InvalidCipherTextException e) {
       log.error(StringUtil.getExceptionDetailInfo(e));
     }
   }
   return fileHead;
 }
  public void handleUpgrade(DlmsEventProcessor processor, DlmsRequest req, DlmsContext context) {

    try {
      boolean isFinished = false; // 是否升级结束
      boolean isSuccess = true; // 命令是否成功

      DlmsRequest dr = new DlmsRequest();
      dr.setRelayParam(req.getRelayParam());
      dr.setMeterId(context.meterId);
      dr.addAllAppendParmas(req.getAllParam());
      dr.setDestAddr(req.getDestAddr());

      if (req.getOperator().equals(DlmsUpgradeAssisant.UPGRADE_00)) {
        isSuccess = updateStep_01_01(req, dr);
      } else if (req.getOperator().equals(DlmsUpgradeAssisant.UPGRADE_01_01)) {
        isSuccess = upgradeStep_01(req, dr);
      } else if (req.getOperator().equals(DlmsUpgradeAssisant.UPGRADE_01)) {
        isSuccess = upgradeStep_02(req, dr);
      } else if (req.getOperator().equals(DlmsUpgradeAssisant.UPGRADE_02)) {
        isSuccess = upgradeStep_03(req, dr);
      } else if (req.getOperator().equals(DlmsUpgradeAssisant.UPGRADE_03)
          || req.getOperator().equals(DlmsUpgradeAssisant.UPGRADE_RESSIUE)) {
        isSuccess = blockTransfering(req, dr);
      } else if (req.getOperator().equals(DlmsUpgradeAssisant.UPGRADE_READMAP)) {
        upgradeStep_04(req, dr);
      } else if (req.getOperator().equals(DlmsUpgradeAssisant.UPGRADE_04)) {
        if (checkBitMap(req, dr)) { // 如果没有漏点,进入第五步
          upgradeStep_05(req, dr);
        }
      } else if (req.getOperator().equals(DlmsUpgradeAssisant.UPGRADE_05)) { // 检测验证是否成功
        if (req.getParams()[0].resultCode == 2) { // 如果返回的是temporary-failure,休息一会再读
          try {
            Thread.sleep(sleepTimeStay06Step * 1000);
          } catch (InterruptedException e) {
          }
        }
        readTransferStatus(dr); // 这里无论返回什么,都去读升级状态
      } else if (req.getOperator().equals(DlmsUpgradeAssisant.UPGRADE_READ_STATUS)) {
        int verfiyFlg = req.getParams()[0].resultData.getEnum();
        if (verfiyFlg == 3) {
          upgradeStep_06(req, dr);
        } else if (verfiyFlg == 2) {
          try {
            Thread.sleep(sleepTimeStay06Step * 1000);
          } catch (InterruptedException e) {
          }
          readTransferStatus(dr);
        } else { // 除了上面两种情况,都是失败
          isSuccess = false;
        }
      } else if (req.getOperator().equals(DlmsUpgradeAssisant.UPGRADE_06)) {
        // 读到的数据与主站下发做比较
        // 如果成功,执行第7步
        {
          upgradeStep_07(req, dr);
        }
      } else if (req.getOperator().equals(DlmsUpgradeAssisant.UPGRADE_07)) {
        // 如果结束 设置finished=true
        if (req.getParams()[0].resultCode == 0) isFinished = true;
        else {
          isSuccess = false;
        }
      }

      // 查询待发送列表中,是否有要升级的请求,如果有,则当前请求判定为失败
      if (context.webReqList.size() > 0) {
        DlmsEvent evt = (DlmsEvent) context.webReqList.get(0);
        DlmsRequest request = (DlmsRequest) evt.getRequest();
        if (request.getOperator() != null && request.getOperator().contains("UPGRADE")) {
          isSuccess = false;
          log.error(
              "meterid="
                  + context.meterId
                  + ".New upgrade request is comming,current upgrade set fail");
        }
      }

      if (!isSuccess) {
        DlmsUpgradeAssisant.getInstance().updateUpgradeInfo(req, UpgradeInfo.FAIL); // 设置为失败
        DlmsUpgradeAssisant.getInstance().updateUpgradeStatus(req, "00");
        if (tracer.isEnabled())
          tracer.trace(
              "Upgrade Failed. MeterId=" + req.getMeterId() + ",Operator=" + req.getOperator());
        return;
      }
      if (!isFinished) {
        DlmsUpgradeAssisant.getInstance().onUpgradeSuccess(dr);
        processor.postWebRequest(dr, null);
      } else {
        // 收尾阶段
        req.addAppendParam(
            DlmsUpgradeAssisant.CURRENT_BLOCK_NUM,
            (Integer) req.getAppendParam(DlmsUpgradeAssisant.BLOCK_COUNT));
        DlmsUpgradeAssisant.getInstance().updateUpgradeInfo(req, UpgradeInfo.SUCCESS); // 设置为成功
        DlmsUpgradeAssisant.getInstance().updateUpgradeStatus(req, "02");
      }
    } catch (Exception e) {
      log.error(StringUtil.getExceptionDetailInfo(e));
      DlmsUpgradeAssisant.getInstance().updateUpgradeInfo(req, UpgradeInfo.FAIL); // 设置为失败
      DlmsUpgradeAssisant.getInstance().updateUpgradeStatus(req, "00");
    }
  }
  /**
   * 收到请求,升级处理
   *
   * @param req
   * @return
   */
  public boolean upgradeProcesser(DlmsRequest req) {
    String logicAddress = "";
    int measurePoint = 0;
    if (req.getRelayParam() != null) {
      RelayParam relayParam = req.getRelayParam();
      logicAddress = relayParam.getDcLogicalAddress();
      measurePoint = relayParam.getMeasurePoint();
    } else {
      logicAddress = req.getMeterId();
      measurePoint = 0;
    }
    try {

      List<UpgradeInfo> infos =
          dbService.getUpgradeInfo(
              new Long((String) req.getAppendParam(DlmsUpgradeAssisant.UPGRADE_ID)));
      if (infos.size() != 1) {
        log.error(
            "Upgrade Request Fail:Info.size="
                + infos.size()
                + ".MeterId="
                + logicAddress
                + ".Tn="
                + measurePoint);
        if (tracer.isEnabled())
          tracer.trace(
              "Upgrade Request Fail:Info.size="
                  + infos.size()
                  + ".MeterId="
                  + logicAddress
                  + ".Tn="
                  + measurePoint);
      }
      req.addAppendParam(DlmsUpgradeAssisant.UPGRADE_ID, infos.get(0).getSoftUpgradeID());

      UpgradeInfo info = infos.get(0);
      int status = info.getStatus();
      DlmsUpgradeAssisant.getInstance().addRequestAppendParams(info, req);

      String fileHead = (String) req.getAppendParam(DlmsUpgradeAssisant.FILE_HEAD);
      String fileType = fileHead.substring(0, 2);

      // 如果是给模块升级,设置dstAddr为  0x0070
      // 根据地址文件头信息获得升级状态
      // req.setDestAddr(0x0070);

      if ("02".equals(fileType)) { // 判断是否是对模块升级
        req.setDestAddr(DlmsMessage.DstAddrToModule);
      }

      boolean isRessiueSuccess = true;
      switch (status) {
        case UpgradeInfo.WAIT_UPGRADE:
          upgradeEnable(req);
          break;
        case UpgradeInfo.WAIT_UPGARDEINIT:
          upgradeInit(req, req, (Integer) req.getAppendParam(DlmsUpgradeAssisant.MAX_SIZE));
          break;
        case UpgradeInfo.UPGRADE_PAUSE:
          upgradeReissueInit(req);
          break;
        case UpgradeInfo.RESSIUE_PAUSE:
          req.addAppendParam(DlmsUpgradeAssisant.IS_TRANSFER_FINISHED, false);
          reissueBlock(req);
          break;
        case UpgradeInfo.CHECK_MAP_FAIL:
          req.setOperator(DlmsUpgradeAssisant.UPGRADE_RESSIUE);
          upgradeStep_04(req, req);
          break;
        case UpgradeInfo.READ_STATUS_FAIL:
          readTransferStatus(req);
          break;
        case UpgradeInfo.VERFIY_FILE_FAIL:
          upgradeStep_05(req, req);
          break;
        case UpgradeInfo.CHECK_FILE_FAIL:
          upgradeStep_06(req, req);
          break;
        case UpgradeInfo.SET_EFFECTTIME_FAIL:
          upgradeStep_07(req, req);
          break;
        default:
          isRessiueSuccess = false;
          log.error(
              "Upgrade File.Status:"
                  + status
                  + " .MeterId="
                  + logicAddress
                  + " .Tn="
                  + measurePoint);
          break;
      }
      if (isRessiueSuccess) {
        DlmsUpgradeAssisant.getInstance().updateUpgradeStatus(req, "01");
        return true;
      }
      return false;
    } catch (Exception e) {
      // 设置升级失败
      log.error("update stoped.", e);
      DlmsUpgradeAssisant.getInstance().updateUpgradeInfo(req, UpgradeInfo.FAIL); // 设置为失败
      DlmsUpgradeAssisant.getInstance().updateUpgradeStatus(req, "00");
      return false;
    }
  }