Newer
Older
br-data-forwarding / src / main / java / com / casic / util / aep / AepCommandSend.java
package com.casic.util.aep;


import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.casic.util.SpringContextUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author cz
 * @date 2024-04-24
 */
@Slf4j
@Data
public class AepCommandSend {

    private String deviceId;
    private String productId;

    private String masterApiKey;
    private String appKey;
    private String appSecret;

    private Long offset = 0L;
    private Long lastGetOffsetTime = 0L;

    private final String CREATE_COMMAND_PATH = "/aep_device_command/command";
    private final String CREATE_COMMAND_LWM2M_PROFILE_PATH = "/aep_device_command_lwm_profile/commandLwm2mProfile";

    public AepCommandSend() {
    }

    public AepCommandSend(String deviceId, String productId) {
        this.deviceId = deviceId;
        this.productId = productId;

        this.masterApiKey = "";
        this.appKey = "";
        this.appSecret = "";
    }

    public AepCommandSend(String deviceId, String productId, String masterApiKey) {
        this.deviceId = deviceId;
        this.productId = productId;
        this.masterApiKey = masterApiKey;
    }

    public AepCommandSend(String deviceId, String productId, String masterApiKey, String appKey, String appSecret) {
        this.deviceId = deviceId;
        this.productId = productId;
        this.masterApiKey = masterApiKey;
        this.appKey = appKey;
        this.appSecret = appSecret;
    }

    /**
     * 处理电信平台的报文解析,并组装回复报文,发送电信平台
     *
     * @param frameStr 业务数据的payload内容
     */
    public int handleAndReply(String frameStr) throws Exception {
        HttpResponse response = createCommand(frameStr);

        JSONObject retObj = new JSONObject();
        try {
            retObj = JSON.parseObject(new String(response.body().getBytes(), StandardCharsets.UTF_8));

            log.info("AEP平台返回消息: {}", retObj.toJSONString());
        } catch (Exception ex) {
            log.error("AEP平台发送失败,异常信息{}", ex.getMessage());
        }

        return (int) retObj.get("code");
    }

    private Long getTimeOffset() {
        AepConfig aepConfig = SpringContextUtil.getBean(AepConfig.class);
        String timeUrl = aepConfig.getTimeUrl();

        try {
            HttpResponse response = HttpRequest.get(timeUrl).execute();
            String timeAg = response.header("x-ag-timestamp");

            return Long.parseLong(timeAg) - System.currentTimeMillis();
        } catch (Exception ex) {
            return 0L;
        }
    }

    private String signature(Long timestamp, String appSecret, String appKey, String masterApiKey, byte[] bodyBytes) throws Exception {
        return Signature.sign(appSecret, appKey, String.valueOf(timestamp), masterApiKey, bodyBytes);
    }

    private HttpResponse createCommand(String frameStr) throws Exception {
        AepConfig aepConfig = SpringContextUtil.getBean(AepConfig.class);

        String baseUrl = aepConfig.getBaseUrl();

        // 消息体
        AepCommandBody body = new AepCommandBody();
        body.setDeviceId(deviceId);
        body.setProductId(productId);
        body.setTtl(aepConfig.getTtl());
        body.setOperator(aepConfig.getOperator());
        body.setLevel(aepConfig.getLevel());
        body.setPayloadString(frameStr);

        log.info("向AEP平台发送消息: {}", JSON.toJSONString(body));

        // 计算时间戳 用于签名
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastGetOffsetTime > 300 * 1000) //300秒调用一次
        {
            offset = getTimeOffset();
            lastGetOffsetTime = currentTime;
        }
        long timestamp = currentTime + offset;

        // 消息头
        Map<String, String> header = new HashMap<>();
        header.put("application", appKey);
        header.put("version", "20190712225145");
        header.put("timestamp", String.valueOf(timestamp));
        header.put("MasterKey", masterApiKey);
        header.put("signature", signature(timestamp, appSecret, appKey, masterApiKey, JSONObject.toJSONString(body).getBytes()));

        return HttpRequest.post(baseUrl + CREATE_COMMAND_PATH)
                .body(JSON.toJSONString(body))
                .addHeaders(header)
                .contentType("application/json; charset=UTF-8")
                .execute();
    }
}