/**
  * 升级使能
  *
  * @param req
  */
 public void upgradeEnable(DlmsRequest req) {
   // TODO:存储升级信息 状态为正在升级
   req.setOperator(DlmsUpgradeAssisant.UPGRADE_00);
   req.setOpType(DLMS_OP_TYPE.OP_SET);
   DlmsObisItem param = req.getParams()[0];
   param.classId = 18;
   param.attributeId = 5;
   param.obisString = "0.0.44.0.0.255";
   DlmsData data = new DlmsData();
   data.setBool(true);
   param.data = data;
 }
 /**
  * 传输位图块请求对象
  *
  * @param req
  * @param dr
  * @param blockNum
  * @param block
  */
 public void blockTransferRequest(DlmsRequest dr, Integer blockNum, byte[] block) {
   setRequestParam(dr, new ObisDescription(18, "0.0.44.0.0.255", 2));
   DlmsData data = new DlmsData();
   DlmsData[] datas = new DlmsData[2];
   datas[0] = new DlmsData();
   datas[0].setDoubleLongUnsigned(blockNum);
   datas[1] = new DlmsData();
   datas[1].setOctetString(block);
   ASN1SequenceOf struct = new ASN1SequenceOf(datas);
   data.setStructure(struct);
   dr.getParams()[0].data = data;
 }
  /**
   * 写升级模式.目前要求至少支持两种模式:0x01升级模式一为针对载波、RF等通信方式,imageBlockSize固定为64字节;0x02升级模式二为针对RS485、GPRS等通信方式,imageBlockSize固定为192字节。
   *
   * @param req
   * @param dr
   * @return
   */
  private boolean updateStep_01_01(DlmsRequest req, DlmsRequest dr) {

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

    dr.setOpType(DLMS_OP_TYPE.OP_SET);
    dr.setOperator(DlmsUpgradeAssisant.UPGRADE_01_01);
    DlmsData data = new DlmsData();
    data.setUnsigned(0x02);
    setRequestParam(dr, new ObisDescription(1, "0.0.44.128.0.255", 2));
    dr.getParams()[0].data = data;

    return true;
  }
  public static void main(String[] args) throws IOException {
    //		DlmsUpgradeAssisant.getInstance().getFtpFileContent(new DlmsRequest());
    //		for(int i=0;i<=400;i++){
    //			byte[] b =
    // DlmsUpgradeHandler.getInstance().getCurUpgradeBlock(DlmsUpgradeHandler.getInstance().getFtpFileContent(new DlmsRequest()), i, 198);
    //			System.out.println(i+"-"+HexDump.toHex(b));
    //		}

    System.out.println(Integer.toBinaryString(0x0f));
    byte[] array = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    System.out.println(array.length / 5 + 1);
    byte[] dest = new byte[5];
    System.arraycopy(array, 0 * 5, dest, 0, 5);
    System.out.println(HexDump.toHex(dest));
    System.arraycopy(array, 1 * 5, dest, 0, 5);
    System.out.println(HexDump.toHex(dest));
    if (3 == array.length / 5 + 1) {
      int remainLen = 5 - (3 * 5 - array.length);
      System.arraycopy(array, 2 * 5, dest, 0, remainLen);
    }
    List<Integer> ressiueBlocks = new ArrayList<Integer>();
    byte[] bitMap = new byte[] {(byte) 0x00, (byte) 0x00};
    DlmsUpgradeHandler.getInstance().getRessiueBlocks(bitMap, 16, ressiueBlocks, 0);
    //		System.arraycopy(array, 2*5, dest, 0, 5);
    System.out.println(
        HexDump.toHex(DlmsUpgradeHandler.getInstance().getCurUpgradeBlock(array, 2, 5)));
    //		DlmsUpgradeHandler.getInstance().getRessiueBlocks(new byte[]{0x08}, 5);
    System.out.println(HexDump.toHex(DlmsUpgradeHandler.getInstance().fileHeadConstruct(null)));

    byte[] apdu =
        HexDump.toArray(
            "C401010004820441FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80");
    GetResponse resp = new GetResponse();
    resp.decode(DecodeStream.wrap(apdu));

    GetResponseNormal grn = (GetResponseNormal) resp.getDecodedObject();

    GetDataResult dd = grn.getResult();
    DlmsData data = dd.getData();
    ASN1BitString s = data.getBitString();
    ressiueBlocks = new ArrayList<Integer>();
    DlmsUpgradeHandler.getInstance().getRessiueBlocks(s.getValue(), 1089, ressiueBlocks, 1);
    System.out.println(ressiueBlocks);
  }
  /**
   * 升级初始化
   *
   * @param req
   * @param dr
   * @param i_maxSize
   */
  private void upgradeInit(DlmsRequest req, DlmsRequest dr, int i_maxSize) {
    dr.removeAppendParam(DlmsUpgradeAssisant.CURRENT_BLOCK_NUM);
    dr.addAppendParam(DlmsUpgradeAssisant.MAX_SIZE, i_maxSize);
    dr.setOpType(DLMS_OP_TYPE.OP_ACTION);
    setRequestParam(dr, new ObisDescription(18, "0.0.44.0.0.255", 1)); // 初始化
    DlmsData data = new DlmsData();
    DlmsData[] datas = new DlmsData[2];
    byte[] content = DlmsUpgradeAssisant.getInstance().getFtpFileContent(req);
    dr.addAppendParam(DlmsUpgradeAssisant.UPGRADE_CONTENT, content);
    dr.addAppendParam(DlmsUpgradeAssisant.BLOCK_COUNT, content.length / i_maxSize); // 块数

    byte[] fileHead = fileHeadConstruct(req);
    dr.addAppendParam(DlmsUpgradeAssisant.FILE_HEAD, HexDump.toHex(fileHead));
    datas[0] = new DlmsData(); // image_identifier
    datas[0].setOctetString(fileHead);
    datas[1] = new DlmsData(); // image_szie
    datas[1].setDoubleLongUnsigned(content.length);
    ASN1SequenceOf struct = new ASN1SequenceOf(datas);
    data.setStructure(struct);
    dr.getParams()[0].data = data;
    dr.setOperator(DlmsUpgradeAssisant.UPGRADE_02);
  }
  /**
   * step7 写入执行时间 新版本软件生效,通过action操作image transfer对象的方法4激活之前步骤中传输的升级包文件。 软件升级时间的格式为array[1] {
   * structure include { time; octet-string[4] date; octet-string[5] } }
   *
   * @param req
   * @param dr
   */
  private void upgradeStep_07(DlmsRequest req, DlmsRequest dr) {
    // 写执行时间
    String strEffcDate = (String) dr.getAppendParam(DlmsUpgradeAssisant.EFFECTIVE_TIME);
    String[] dateTime = strEffcDate.split(" ");
    DlmsData[] effcDate = new DlmsData[2];
    effcDate[0] = new DlmsData();
    effcDate[0].setDlmsTime(dateTime[1]);
    effcDate[1] = new DlmsData();
    effcDate[1].setDlmsDate(dateTime[0]);
    DlmsData[] array = new DlmsData[] {new DlmsData()};
    ASN1SequenceOf struct = new ASN1SequenceOf(effcDate);
    array[0].setStructure(struct);
    DlmsData data = new DlmsData();
    try {
      data.setArray(array);
    } catch (IOException e) {
      log.error(StringUtil.getExceptionDetailInfo(e));
    }

    setRequestParam(dr, new ObisDescription(22, "0.0.15.0.2.255", 4));
    dr.getParams()[0].data = data;
    dr.setOpType(DLMS_OP_TYPE.OP_SET);
    dr.setOperator(DlmsUpgradeAssisant.UPGRADE_07);
  }