#ifndef __DOWNLINK_H__
#define __DOWNLINK_H__

#include "stm32f10x.h"
#include "../network_mgr/net_proc.h"
#include "../encode/encodeOpt.h"

#define COLLECT_MAX_NUM 16
#define TAX_MAX_NUM     2
#define GUN_MAX_NUM     8

#define DOWNLINK_CONFIG_TYPE 0x10 //0x65

#define CONFIG_ADDR          0X100
#define CONFIG_WRITE         0x01

typedef struct _tax_conf
{
    uint8_t tax_id;                //报税口编号
    uint8_t gun_num;               //加油枪数量
    uint8_t gunid[GUN_MAX_NUM];    //加油枪编号
    uint8_t alrd_sn;             //是否查询过加油机的信息
    uint8_t factory;	      /*厂家 1：英泰 2：拓盛 */
    uint8_t status;              // 报税口的状态 ，是否连接
    uint8_t encryption;          // 报税口的加密状态 ，由服务器下发的，暂停没有用于
    uint8_t monitor_serino[16];  //序列号
}__attribute__((packed)) tax_conf_t;
	
typedef struct _collect_conf
{
    uint32_t collect_no; //采集器编号
    uint8_t tax_num;     //报税口数量
    uint8_t tax_type;    //报税口类型，明文或密文
    uint8_t collect_status; // 采集器的状态 在线或是离线 0 离线 1：在线
    uint8_t coll_send_num; // 采集器发送的次数
    tax_conf_t tax_conf[TAX_MAX_NUM];
}__attribute__((packed)) collect_conf_t;


#define INSTALL_5A 0x5A  // 完成过程，配置第一步时用到，最后一步完成，则清零
typedef struct _downlink_config
{
    uint8_t config_flag;   //采集器配置标记
    uint32_t gateway_id;   //网关id
    uint8_t collect_num;   //采集器数量
    uint8_t bInstallFinish; // 完成是否完成， 非5A，则为完成，如果为5A，则为安装的过程，// 完成过程，配置第一步时用到，最后一步完成，则清零
    collect_conf_t collect_conf[COLLECT_MAX_NUM];
}__attribute__((packed)) downlink_config_t;
extern downlink_config_t downlink_config;

/*==============================================================*/
/* 以下是服务器下发 需要用到的解析*/

/* 升级信息下行 0x1001 */
typedef struct _downlink_system_cmd_0x1001 {
    uint16_t targetType; // 设备类型（0x0101：网关；0x0201；采集器：0x0301:液位仪采集器；0x0401：屏采集器）
    uint32_t sn; // sn 编号
    uint16_t taskNo; // 任务号
    uint8_t urlLen; // URL长度
    char url[128]; // url地址
}__attribute__((packed)) downlinkSysCmd0x1001;
/* 切换mqtt IP地址 0x1003 */
typedef struct _downlink_system_cmd_0x1003 {
    uint32_t gateway_sn; //  网关SN
    uint16_t targettype; // 类型 0x0101网关  0x0201:采集器 0x0301:液位仪
    uint8_t iplen; // ip地址长度
    uint8_t portlen; // 端口长度
    uint8_t userlen; // 用户名长度
    uint8_t pwdlen;   // 密码长度
//    char port[6]; // 端口号
//    char ip[32]; //IP地址
//    char admin[8]; // 用户名
//    char password[16]; // 密码
    uint8_t str[76];
}__attribute__((packed)) downlinkSysCmd0x1003;

/* 采集器路由信息初始化 0x1011 */
typedef struct _configmsg_{
    uint32_t  collectSn;
    uint8_t  comEncrypt[2]; //报税口的加密状态

}__attribute__((packed)) configMsg;

typedef struct _downlink_system_cmd_0x1011 {
    uint32_t gateway_id;   //网关SN
    uint8_t configNo;      // 配置流水号
    uint8_t collect_num;   //采集器数量
    configMsg cfigMsg[16];
}__attribute__((packed)) downlinkSysCmd0x1011;

/* 刷新税控序列号 0x1012*/
typedef struct _downlink_system_cmd_0x1012_{
    uint32_t gateway_sn; // 网关SN
    uint32_t coll_sn;    // 采集器编号
    uint8_t tax_no;  // 报税口编号
}__attribute__((packed)) downlinkSysCmd0x1012;

/* 设备重新启动 0x1021*/
typedef struct _downlink_system_cmd_0x1021_{
    uint16_t targetType; // 设备类型（0x0101：网关；0x0201；采集器：0x0301:液位仪采集器；0x0401：屏采集器）
    uint32_t sn; // 设备sn号
}__attribute__((packed)) downlinkSysCmd0x1021;

/* 时间轮询间隔 */
typedef struct _downlink_system_cmd_0x1013_{
    uint32_t gateway_sn; // 网关SN
    uint16_t time_interval; // 时间轮询
}__attribute__((packed)) downlinkSysCmd0x1013;



/* 系统信息（0x01) 0x1016 指令 切换lora信道信息 */
typedef struct _downlink_system_cmd_0x1016_{
    uint8_t paraflag ;     // 标志
    uint8_t loraIndex;   // lora通道号
    uint32_t freq;       // lora 发射频率
    uint8_t power;       // 发射功率
    uint8_t bandwidth;   // 带宽
    uint8_t spreadingfactor; // 扩频因子
    uint8_t codingrate;     // 纠错编码率
    uint16_t preambleLen;    // 前导码长度
}__attribute__((packed)) downlinkSysCmd0x1016;

/* 系统信息（0x01) 0x1017 指令 读取 lora信道信息 */
typedef struct _downlink_system_cmd_0x1017_{
    uint32_t gateway_sn; // 网关编号
    uint32_t coll_sn;    // 采集器编号
}__attribute__((packed)) downlinkSysCmd0x1017;

/* 系统信息(0x01) 0x1018 指令， 手动刷新税控序列号 */
typedef struct _downlink_system_cmd_0x1018_{
    uint32_t gateway_sn; // 网关编号
    uint8_t prara;       // 参数
    uint32_t coll_sn;    // 采集器编号
    uint8_t taxNo;       // 报税口号
    uint32_t reserve;    // 预留
}__attribute__((packed)) downlinkSysCmd0x1018;

enum {
    CONFIG_STEP_01 = 0x01, // 配置第一步
    CONFIG_STEP_02 = 0x02, // 配置第二步 配置显示屏
    CONFIG_STEP_03 = 0x03, // 配置第三步 配置显示屏
    CONFIG_STEP_04 = 0x04, // 配置第四步 配置编码器路由表
    CONFIG_STEP_05 = 0x05, // 配置 第五步，配置编码器使能
    CONFIG_STEP_09 = 0x09, // 配置第九步 完成
};
/* 系统信息(0x01) 0x1019 带屏或不带屏的路由信息初始化 */
typedef struct _xspDnMsg_{
    uint32_t xsp_sn; // 显示屏的SN
    uint8_t cbusId; // 总线索引
    uint8_t cdaId; // 报税口采集器索引
    uint8_t portid; // 对应的报税口号
    uint8_t gunid; // 对应的枪号
    uint8_t priceid; // 单价屏索引

}__attribute__((packed)) xspDnMsg;


typedef struct _downlink_system_cmd_0x1019_01{ //第一步
    uint8_t bencoder;  // 是否有编码器 0：没有  1：有
    uint8_t collect_num;   //采集器数量
    configMsg cfigMsg[16];
}__attribute__((packed)) downlink0x1019_01;
typedef struct _downlink_system_cmd_0x1019_02{ // 第二步 第三步
    uint8_t frame_no;  // 是否有后续帧
    uint8_t groupNo;  // 组数
    xspDnMsg _xspMsg[16]; //显示屏的信息 【16组】
}__attribute__((packed)) downlink0x1019_02;
typedef struct _downlink_encode_{
    uint8_t daColl;
    uint8_t daPort;
    uint8_t daGun;
    uint8_t busColl;
    uint8_t busPort;
    uint8_t busGun;
}__attribute__((packed)) encodeda;

typedef struct _downlink_system_cmd_0x1019_04 { // 第四步
    uint8_t reserve; // 预留
    uint8_t frame_no; // 是否有后续帧
    uint8_t groupNo; // 组数
    encodeda da[16];
}__attribute__((packed)) downlink0x1019_04;


typedef struct _downlink_system_cmd_0x1019_05 { // 第五步
    uint8_t reserve; // 预留
    uint8_t enableTime; // 编码器启用的时间 0xFF:永久启用 0x00：不启用，其它：单位为分钟
}__attribute__((packed)) downlink0x1019_05;

typedef struct _downlink_system_cmd_0x1019_09{ // 第九步
    uint32_t reserve; // 预留
}__attribute__((packed)) downlink0x1019_09;
typedef union _downlink_system_cmd_0x1019_step {
    downlink0x1019_01 step1;
    downlink0x1019_02 step2;
    downlink0x1019_04 step4;
    downlink0x1019_05 step5;
    downlink0x1019_09 step9;
}__attribute__((packed)) dwonlink0x1019_step;

typedef struct _downlink_system_cmd_0x1019 {
    uint32_t gateway_sn; // 网关编号
    uint8_t configNo; // 配置流水号
    uint8_t step;     // 步骤
    dwonlink0x1019_step da;
}__attribute__((packed)) downlinkSyscmd0x1019;

typedef struct _downlink_system_cmd_0x1020 {
    uint32_t gateway_sn; // 网关编号
    uint32_t coll_sn;     // 采集器编号
    uint32_t reserve;  // 预留
    uint8_t taxNo01;   // 报税口1 , 从1开始，如果为0，则无效
    uint8_t gunNum01;  // 对应该报税口1的枪的个数
    uint8_t taxNo02;   // 报税口2，从1开始，如果为0，则无效
    uint8_t gunNum02;  // 对应该报税口2的枪的个数
}__attribute__((packed)) downlinkSysCmd0x1020;

/* 编码器路由表是否启用 */
typedef struct _downlink_system_cmd_0x1022_{
    uint32_t gateway_sn; // 网关SN
    uint16_t tagettype; // 设备类型
    uint8_t  benable; // 编码器路由表是否启用 0：未启用 1：启用
    uint32_t reserve;  // 预留
}__attribute__((packed)) downlinkSysCmd0x1022;
/* 采集器设备设置 0x1023*/
typedef struct _downlink_system_cmd_0x1023_{
    uint32_t gateway_sn; // 网关SN
    uint16_t targetType; // 设备类型（0x0101：网关；0x0201；采集器：0x0301:液位仪采集器；0x0401：屏采集器）
    uint32_t sn; // 设备sn号
    uint8_t cmd; // 指令
    uint32_t reserve; // 预留
}__attribute__((packed)) downlinkSysCmd0x1023;
/* 读取报税口数据  0x1034 */
typedef struct _downlink_system_cmd_0x1034_{
    uint32_t gateway_sn; // 网关SN
    uint8_t  read_type; // 读取类型  0xff:全站读取  0x00:只读取一个
    uint32_t coll_sn;    // 采集器SN
    uint8_t taxNo;       // 报税口编号 从1开始
    uint8_t gunNo;       // 枪的编号 从1开始
    uint32_t reserve;    // 预留
}__attribute__((packed)) downlinkSysCmd0x1034;
/* 拓盛密文实时读取 0x1051*/
typedef struct _downlink_system_cmd_0x1051_{
    uint32_t gateway_sn; // 网关SN
    uint32_t coll_sn;    // 采集器sn号
    uint8_t  taxNo;      // 报税口号
    uint8_t  benable;    // 是否启用时实读取 0：非时实 1：时实
    uint32_t reserve;    // 预留
}__attribute__((packed)) downlinkSysCmd0x1051;

/* 透传指令（直接透传到采集器） 0x1052*/
typedef struct _downlink_system_cmd_0x1052_{
    uint32_t gateway_sn; // 网关SN
    uint32_t coll_sn;    // 采集器sn号
    uint8_t  taxNo;      // 报税口号
    uint8_t  reserve;    // 预留
    uint16_t palen;      // 数据长度
    uint8_t  info[128];  // 透传的数据
}__attribute__((packed)) downlinkSysCmd0x1052;

/* 0x01---0x1053 0x1023指令的格式 */
typedef struct _downlink_system_cmd_0x1053_
{
    uint16_t firstLevelType;    //一级设备类型
    uint32_t firstLevelSn;      //一级设备SN
    uint16_t rcvDevType;        // 接收设备类型
    uint32_t rcvDevSn;          // 接收设备SN
    uint16_t targetDevType;     // 目标设备类型
    uint32_t targetDevSn;       // 目标设备SN
    uint32_t reserve;
    uint8_t optType;            // 执行操作1：设置 2：读取
    uint8_t cmdType;            // 执行指令 1：编码器与抬枪信号正反序
    uint16_t cmdVal;      // 1:正序 2：反序 其它：无
    uint32_t reserve01;           // 预留
}__attribute__((packed))downlinkSysCmd0x1053;




/* 状态信息 固件信息下行 0x1001*/
typedef struct _downlink_status_cmd_0x1001_{
    uint32_t gateway_sn; // 网关ID
    uint16_t targetType; // 设备类型（0x0101：网关；0x0201；采集器：0x0301:液位仪采集器；0x0401：屏采集器）
    uint32_t sn; // 设备编号
}__attribute__((packed)) downlinkStatusCmd0x1001;

/* 异常类下行 0x1001*/
typedef struct _downlink_log_cmd_0x1001_{
    uint32_t gateway_sn; // 网关ID
    uint16_t targetType; // 设备类型（0x0101：网关；0x0201；采集器：0x0301:液位仪采集器；0x0401：屏采集器）
    uint8_t bEnable;  // 0:关闭日志上报  1：开启日志上报
    uint32_t timer; // 开启时间 单位：秒
    uint32_t reserve; // 预留
}__attribute__((packed)) downlinkLogCmd0x1001;
/* 异常类下行 0x1002*/
typedef struct _downlink_log_cmd_0x1002_{
    uint32_t gateway_sn; // 网关ID
    uint16_t targetType; // 设备类型（0x0101：网关；0x0201；采集器：0x0301:液位仪采集器；0x0401：屏采集器）
    uint8_t bEnable;  // 0:关闭日志上报  1：开启日志上报
    uint32_t timer; // 开启时间 单位：秒
    uint8_t opentype; // 打开类型
    uint32_t collSN ; // 采集器SN
    uint8_t taxno; // 报税口编号
    uint8_t gunno; //枪的编号
    uint32_t reserve; // 预留
}__attribute__((packed)) downlinkLogCmd0x1002;

extern void downlink_init(void);

int downlink_gateway_analyze(uint8_t *data, uint16_t len);
#endif

