Ver código fonte

1. 优化4G频段选择功能,优先使用B5通道,并放开其他通道的限制
2. 优化sprintf函数调用,更改为占用空间更小的自定义函数
3. 按照大表修改的方案,更新小表关于修改日期和修改底读时的结算方案代码.
4. 使用版本区分的大表小表来修改参数和部分代码条件编译调用.

wxl 12 horas atrás
pai
commit
1c03324f7a
6 arquivos alterados com 420 adições e 250 exclusões
  1. 125 58
      Users/app_nb/app_nb.c
  2. 8 7
      Users/app_nb/app_nb.h
  3. 166 97
      Users/bill/bill.c
  4. 13 10
      Users/bill/bill.h
  5. 96 66
      Users/param/param.c
  6. 12 12
      Users/param/param.h

+ 125 - 58
Users/app_nb/app_nb.c

@@ -24,6 +24,7 @@ NbAppFrame_t __attribute__((aligned(4))) NbAppFrame;
 uint8_t Nb_rx_data(void);
 void nb_run_init(void)
 {
+    nb_power_off();
     lpuart0_set_rx_itf(NbRxCh); // nb串口中断
     // NbRun.rx_flag = FALSE;
     NbRun.rx_over_time = 0;
@@ -486,7 +487,9 @@ int8_t Nb_check_rec_valid(uint8_t state, char *ack)
 
         return 1; // 收到正确回复,进行下一步
     }
-    if (strstr((char *)&NbRun.rx_buf[0], "\r\nOK\r\n") != NULL || strstr((char *)&NbRun.rx_buf[0], "\r\nERROR\r\n") != NULL)
+    // if (strstr((char *)&NbRun.rx_buf[0], "\r\nOK\r\n") != NULL || strstr((char *)&NbRun.rx_buf[0], "\r\nERROR\r\n") != NULL)
+    if (strstr((char *)&NbRun.rx_buf[0], "\r\nERROR\r\n") != NULL)
+
     {
 
         return -1; // 错误回复,重新发送
@@ -535,7 +538,7 @@ uint8_t settlement_day_upload_check(void)
     //////////////////////确定当天上报是否是结算日上报/////////////////////////////////////
     int32_t now, start;
     now = (int32_t)(3600 * rr->hour + 60 * rr->minute + rr->second);
-    start = (int32_t)(Paramx.report_base_hour * 3600 + Paramx.report_base_min * 60 + (Paramx.report_base_sec & 0xfe));
+    start = (int32_t)(Paramx.report_base_hour * 3600 + Paramx.report_base_min * 60 + (Paramx.report_base_sec & 0xfc));
     if (Paramx.settlement_day == 0)
     {
         return 0;
@@ -572,7 +575,7 @@ uint8_t regular_upload_check(void)
     int32_t now, start;
 
     now = (int32_t)(3600 * rr->hour + 60 * rr->minute + rr->second);
-    start = (int32_t)(Paramx.report_base_hour * 3600 + Paramx.report_base_min * 60 + (Paramx.report_base_sec & 0xfe));
+    start = (int32_t)(Paramx.report_base_hour * 3600 + Paramx.report_base_min * 60 + (Paramx.report_base_sec & 0xfc));
 
     if (now < start)
         return 0; // 未到上报时间
@@ -597,8 +600,8 @@ uint8_t dma_upload_check(void)
     rtc_run_t *rr;
     get_rtc_run(&rr);
 
-    start_sec = (int32_t)(3600 * Paramx.dma_report_start[0] + 60 * Paramx.dma_report_start[1] + Paramx.dma_report_start[2]);
-    end_sec = (int32_t)(3600 * Paramx.dma_report_end[0] + 60 * Paramx.dma_report_end[1] + Paramx.dma_report_end[2]);
+    start_sec = (int32_t)(3600 * Paramx.dma_report_start[0] + 60 * Paramx.dma_report_start[1] + (Paramx.dma_report_start[2] & 0xfc));
+    end_sec = (int32_t)(3600 * Paramx.dma_report_end[0] + 60 * Paramx.dma_report_end[1] + (Paramx.dma_report_end[2] & 0xfc));
     now_sec = (int32_t)(3600 * rr->hour + 60 * rr->minute + rr->second);
 
     if (now_sec < start_sec || now_sec > end_sec + 3)
@@ -994,10 +997,10 @@ int8_t nb_read_5min_record_ack(void)
         start = limit_start_tm;
     }
 
-    if (datecmp(end, now_tm) > 0)
-    {
-        end = now_tm;
-    }
+    // if (datecmp(end, now_tm) > 0)//允许终止时间大于当前时间
+    //{
+    //    end = now_tm;
+    // }
 
     // ?μУ?
     if (datecmp(start, end) > 0)
@@ -1461,7 +1464,7 @@ void rtc_add_secs(TIME_DEF *dest, rtc_run_t *src, unsigned short secs)
     dat = (src->minute + dat) / 60;
     dest->hour = (dat + src->hour) % 24;
 }
-int8_t connected_flag;
+uint8_t connected_flag;
 void NbTread(void)
 {
     uint32_t retry_time;
@@ -1484,14 +1487,26 @@ void NbTread(void)
         if (at_cmd_send(npos++, NB_ATE0, NB_ATE0_ACK, 3, 2) == -1) // 关闭回显
             break;
         /////////////设置频段//////////////////////////
-        if (Paramx.nb_band_flag != 0)
+        ncnt = Paramx.nb_band_flag;
+        /////////////设置频段//////////////////////////
+        if (ncnt != 2)
         {
-            // if (at_cmd_send(npos++, "AT+QCFG=\"band\",0,0x10,0,1\r\n", NB_AT_ACK, 3, 5) == -1)
-            //   break;
-            if (at_cmd_send(npos++, "AT+QCFG=\"band\",0,0x008800D5,0,1\r\n", NB_AT_ACK, 3, 5) == -1)
-                break;
-
-            set_nb_band();
+            if (ncnt > 2)
+            {
+                ncnt = 0;
+            }
+            if (ncnt == 0)
+            {
+                if (at_cmd_send(npos++, "AT+QCFG=\"band\",0,0x10,0,1\r\n", NB_AT_ACK, 3, 5) == -1)
+                    break;
+            }
+            if (ncnt == 1)
+            {
+                if (at_cmd_send(npos++, "AT+QCFG=\"band\",0,0x008800D5,0,1\r\n", NB_AT_ACK, 3, 5) == -1)
+                    break;
+            }
+            ncnt++;
+            set_nb_band(ncnt);
             if (at_cmd_send(1, NB_CFUN0, NB_AT_ACK, 3, 3) == -1)
                 break;
             rt_thread_mdelay(1000);
@@ -1703,12 +1718,12 @@ void NbTread(void)
 #endif
 
                     vflag = 0;
-                    sprintf(ncdp_str, "AT+QIOPEN=1,0,\"TCP\",\"%d.%d.%d.%d\",%d,0,0\r\n", // 倒数第二个0:本地ip自动 最后一个0: 缓存模式
-                            Paramx.main_server_ip[0],
-                            Paramx.main_server_ip[1],
-                            Paramx.main_server_ip[2],
-                            Paramx.main_server_ip[3],
-                            Paramx.main_server_port);
+                    build_tcp_open_cmd(ncdp_str, //"AT+QIOPEN=1,0,\"TCP\",\"%d.%d.%d.%d\",%d,0,0\r\n", // 倒数第二个0:本地ip自动 最后一个0: 缓存模式
+                                       Paramx.main_server_ip,
+                                       // Paramx.main_server_ip[1],
+                                       //  Paramx.main_server_ip[2],
+                                       //  Paramx.main_server_ip[3],
+                                       Paramx.main_server_port);
 
                     if (at_cmd_send(npos, ncdp_str, "+QIOPEN: 0,", 2, 10) == -1) // 建立TCP连接,等待连接成功
                         break;
@@ -1752,12 +1767,12 @@ void NbTread(void)
 #ifdef APP_DEBUG_PRINT
                     LOG("sub service upload\r\n");
 #endif
-                    sprintf(ncdp_str, "AT+QIOPEN=1,0,\"TCP\",\"%d.%d.%d.%d\",%d,0,0\r\n", // 倒数第二个0:本地ip自动 最后一个0: 缓存模式
-                            Paramx.sub_server_ip[0],
-                            Paramx.sub_server_ip[1],
-                            Paramx.sub_server_ip[2],
-                            Paramx.sub_server_ip[3],
-                            Paramx.sub_server_port);
+                    build_tcp_open_cmd(ncdp_str,             //"AT+QIOPEN=1,0,\"TCP\",\"%d.%d.%d.%d\",%d,0,0\r\n", // 倒数第二个0:本地ip自动 最后一个0: 缓存模式
+                                       Paramx.sub_server_ip, //[0],
+                                                             // Paramx.sub_server_ip[1],
+                                                             //  Paramx.sub_server_ip[2],
+                                                             //   Paramx.sub_server_ip[3],
+                                       Paramx.sub_server_port);
 
                     if (at_cmd_send(npos, ncdp_str, "+QIOPEN: 0,", 2, 10) == -1) // 建立TCP连接,等待连接成功
                         break;
@@ -2023,7 +2038,7 @@ static void BuildDataReportMeter(rtc_run_t *rr, uint8_t *data)
 #endif
     // water temperature
     if (WaterTemp > 100.0f || WaterTemp < 0.0f)
-        temp = -1;
+        temp = 0x8000; // wxl 2026-5-22
     else
         temp = (uint32_t)(WaterTemp * 10 + 0.5);
 #ifdef DEBUG_NB
@@ -2040,21 +2055,24 @@ static void BuildDataReportMeter(rtc_run_t *rr, uint8_t *data)
         data[21] = (uint8_t)(WaterPressure * 100);
     }
     else
-        data[21] = 0x00; // 无压力传感器,修改为0
+        data[21] = 0;
 
 #ifdef DEBUG_NB
     //	data[21]=213;
 #endif
 
     // battery voltage unit: 0.1V
-    /*   if (McuVbat > McuVTxbat)
-       { // 判断哪个电池低就上传哪个数据
-           temp = McuVTxbat / 100;
-       }
-       else
-           temp = McuVbat / 100;
-   */
-    temp = McuVbat / 100; // wxl2026-6-2
+#if VER_MODULE == 3
+    if (McuVbat > McuVTxbat)
+    { // 判断哪个电池低就上传哪个数据
+        temp = McuVTxbat / 100;
+    }
+    else
+        temp = McuVbat / 100;
+#else
+    temp = McuVbat / 100;
+#endif
+
     data[22] = (unsigned char)temp;
 
     data[23] = 0x14;
@@ -2234,14 +2252,9 @@ static void BuildMonthRecord(rtc_run_t *rr, uint8_t *data)
     for (i = 0; i < 2; i++)
     {
         date = prev_month(date);
-        vflag = read_month_bill((uint8_t)(date >> 16), (uint8_t)(date >> 8), &bill);
+        vflag = get_month_used_bill((uint8_t)(date >> 16), (uint8_t)(date >> 8), &bill);
         if (vflag != 0)
             continue; // no data
-        if (bill.date[0] != (uint8_t)(date >> 16) || bill.date[1] != (uint8_t)(date >> 8))
-            continue; //  不是当月数据
-        data[i * 11] = 0x14;
-        data[i * 11 + 1] = bill.date[0];
-        data[i * 11 + 2] = bill.date[1];
         data[i * 11] = 0x14;
         data[i * 11 + 1] = bill.date[0];
         data[i * 11 + 2] = bill.date[1];
@@ -2267,11 +2280,11 @@ static void BuildDayRecord(rtc_run_t *rr, uint8_t *data)
     for (i = 0; i < 5; i++)
     {
         date = prev_day(date);
-        vflag = read_day_bill((uint8_t)(date >> 8), (uint8_t)date, &bill);
+        vflag = get_day_used_bill((uint8_t)(date >> 16), (uint8_t)(date >> 8), (uint8_t)date, &bill);
         if (vflag != 0)
             continue; // no data
-        if (bill.date[0] != (uint8_t)(date >> 16) || bill.date[1] != (uint8_t)(date >> 8) || bill.date[2] != (uint8_t)date)
-            continue; // 不是当天的数据
+                      // if (bill.date[0] != (uint8_t)(date >> 16) || bill.date[1] != (uint8_t)(date >> 8) || bill.date[2] != (uint8_t)date)
+                      //     continue; // 不是当天的数据
         data[i * 12] = 0x14;
         data[i * 12 + 1] = bill.date[0];
         data[i * 12 + 2] = bill.date[1];
@@ -2303,13 +2316,9 @@ static void BuildHourRecord(rtc_run_t *rr, uint8_t *data)
     data[3] = (unsigned char)(date);
     for (i = 0; i < 24; i++)
     {
-        vflag = read_hour_bill((uint8_t)date, i, &bill);
+        vflag = get_hour_used_bill(data[1], data[2], data[3], i, &bill);
         if (vflag != 0) // 数据不合法,放弃
             continue;
-        if ((bill.date[0] != data[1]) || (bill.date[1] != data[2]) || (bill.date[2] != data[3]))
-        {
-            continue;
-        } // 不是当前日期数据,丢弃
         memcpy(&data[4 + i * 3], bill.fw_used, 3);
         memcpy(&data[4 + 72 + i * 3], bill.bw_used, 3);
         data[4 + 144 + i] = bill.pressure;
@@ -2680,7 +2689,7 @@ int8_t get_code(uint8_t *buf, const char *keyword, uint16_t dat_len, int16_t *re
     *ret = dat;
     return 1;
 }
-
+#ifdef NB_AUTO_GET_NET_TIME // 自动获取网络时间
 //+QNTP: 0,"2019/09/09,01:32:42+32"
 void save_datetime_from_at(uint8_t *buf, uint16_t dat_len)
 {
@@ -2720,7 +2729,7 @@ void save_datetime_from_at(uint8_t *buf, uint16_t dat_len)
     SetRtcTime(&tm);
     save_cur_flow_flag = 1;
 }
-
+#endif
 //+QENG: "servingcell","NOCONN","LTE","FDD",460,11,EA6CE03,77,100,1,5,5,EA15,-94,-8,-66,24,26
 //                                                                           rsrp rwrq rssi sinr
 uint8_t get_nb_signal(uint8_t *buf, uint16_t dat_len)
@@ -2730,9 +2739,10 @@ uint8_t get_nb_signal(uint8_t *buf, uint16_t dat_len)
     {
         return 0;
     }
-
-    char temp[256] = {0};
-    memcpy(temp, buf, sizeof(temp) - 1);
+    if (dat_len > 200)
+        return 0;
+    char temp[200] = {0};
+    memcpy(temp, buf, dat_len);
 
     char *token = NULL;
     char *tokens[20]; // 足足够容纳所有分割的子字符串
@@ -2813,3 +2823,60 @@ uint8_t check_main_service_flag(void)
     }
     return vflag;
 }
+
+/**
+ * @brief 极简的无符号整型转字符串函数 (替代 itoa,减少对 stdlib 的依赖)
+ * @param value 待转换的数值
+ * @param str   转换后的字符串缓冲区 (需保证至少6字节空间)
+ * @return 指向字符串缓冲区的指针
+ */
+static char *uint_to_str(uint16_t value, char *str)
+{
+    char buf[6];
+    uint8_t i = 0;
+    if (value == 0)
+    {
+        str[0] = '0';
+        str[1] = '\0';
+        return str;
+    }
+    while (value > 0)
+    {
+        buf[i++] = (value % 10) + '0';
+        value /= 10;
+    }
+    uint8_t len = i;
+    for (uint8_t j = 0; j < len; j++)
+    {
+        str[j] = buf[len - 1 - j];
+    }
+    str[len] = '\0';
+    return str;
+}
+
+/**
+ * @brief 构建 NB-IoT TCP 连接的 AT 指令 (替代 sprintf,大幅减少代码量)
+ * @param out_str  输出的指令字符串缓冲区
+ * @param ip       4字节IP地址数组
+ * @param port     端口号
+ */
+void build_tcp_open_cmd(char *out_str, uint8_t *ip, uint16_t port)
+{
+    char num_buf[6];
+    strcpy(out_str, "AT+QIOPEN=1,0,\"TCP\",\"");
+    uint_to_str(ip[0], num_buf);
+    strcat(out_str, num_buf);
+    strcat(out_str, ".");
+    uint_to_str(ip[1], num_buf);
+    strcat(out_str, num_buf);
+    strcat(out_str, ".");
+    uint_to_str(ip[2], num_buf);
+    strcat(out_str, num_buf);
+    strcat(out_str, ".");
+    uint_to_str(ip[3], num_buf);
+    strcat(out_str, num_buf);
+    strcat(out_str, "\",");
+    uint_to_str(port, num_buf);
+    strcat(out_str, num_buf);
+    strcat(out_str, ",0,0\r\n");
+}

+ 8 - 7
Users/app_nb/app_nb.h

@@ -17,8 +17,8 @@ extern "C"
 #define MB_MAX_RETRY_GATT_QUERY_TIME 4
 #define QUERY_RETRY_TIME 90
 
-//#define NB_AUTO_GET_NET_TIME	//自动获取网络时间
-	
+  // #define NB_AUTO_GET_NET_TIME	//自动获取网络时间
+
 #define NB_FLAG_ARG_VLD (0x0001u)
 
 #define NB_AT "AT\r\n"
@@ -140,7 +140,7 @@ extern "C"
     COAP_CFUN0 = 13,       //
     COAP_NCSEARFCN = 14,   // 清除先验频点
     COAP_ERROR = 15,       // 设置错误码
-		COAP_NNMI = 16,        // 设置直吐模式
+    COAP_NNMI = 16,        // 设置直吐模式
     COAP_CGPADDR = 17,     // 查询注网是否成功
     COAP_IMEI = 18,        // IMEI
     COAP_CIMI = 19,        // CIMI
@@ -360,6 +360,7 @@ extern "C"
   extern void update_rtc_run(void);
   extern void NbTread(void);
   extern int8_t at_cmd_send(uint8_t stat, char *cmd_str, char *ack, uint16_t retry_time, uint8_t time_out);
+  extern int8_t at_cmd_send2(uint8_t stat, char *cmd_str, char *ack1, char *ack2, uint16_t retry_time, uint8_t time_out);
   extern uint8_t G_NB_CAN_DEEP_SLEEP;
   extern UPLOAD_DEF upload_dat;
   extern int8_t datecmp(tm_t date1, tm_t date2);
@@ -370,14 +371,14 @@ extern "C"
   extern uint8_t NB_CHECK_TDC_COMPLETE_FLAG;
   // #ifdef DEBUG_LOG_WARM
   extern void Debug_log(void);
-	extern uint8_t memstr_exist(uint8_t *, size_t, const char *, size_t);
-	  extern int8_t get_code(uint8_t *buf, const char *keyword, uint16_t dat_len, int16_t *ret);
+  extern uint8_t memstr_exist(uint8_t *, size_t, const char *, size_t);
+  extern int8_t get_code(uint8_t *buf, const char *keyword, uint16_t dat_len, int16_t *ret);
   extern void save_datetime_from_at(uint8_t *buf, uint16_t dat_len);
   extern uint8_t get_nb_signal(uint8_t *buf, uint16_t dat_len);
   extern uint8_t check_sub_service_flag(void);
   extern uint8_t check_main_service_flag(void);
-	extern int8_t at_cmd_send2(uint8_t stat, char *cmd_str, char *ack1, char *ack2, uint16_t retry_time, uint8_t time_out);
-// #endif
+  extern void build_tcp_open_cmd(char *out_str, uint8_t *ip, uint16_t port);
+  // #endif
 #ifdef __cplusplus
 }
 #endif

+ 166 - 97
Users/bill/bill.c

@@ -17,6 +17,7 @@ res_bill_t bak_hour_cum_flow;
 bill_5min_ctrl_def bak_5min_cum_flow;
 uint8_t StartUp = 0;
 uint8_t global_settle_flag = 0;
+
 void bill_init(void)
 {
 	BillRun.fw_use_hour = 0.0f;
@@ -154,9 +155,25 @@ void set_month_used_bill(uint8_t year, uint8_t month, uint8_t day)
 	bill_t month_bill;
 	uint16_t len = sizeof(bill_t);
 	uint32_t addr = MONTH_BILL_START_ADDR + len * MONTH_BILL_INDEX(year, month);
+	if (CheckDateValid(year, month, day, 0, 0, 0) == 0)
+		return;
+	/////////////////////如果数据已经存在,则在原来的基础上累加////////////////////////////////////////
+	uint8_t ret;
+	ret = get_month_used_bill(year, month, &month_bill);
+	if (ret == 0)
+	{
+		fw_used = month_bill.fw_used;
+		bw_used = month_bill.bw_used;
+	}
+	else
+	{
+		fw_used = 0;
+		bw_used = 0;
+	}
+	////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-	fw_used = get_month_fw_used_bill();
-	bw_used = get_month_bw_used_bill();
+	fw_used += get_month_fw_used_bill();
+	bw_used += get_month_bw_used_bill();
 
 	month_bill.flag = 1;
 	month_bill.date[0] = year;
@@ -180,9 +197,26 @@ void set_day_used_bill(uint8_t year, uint8_t month, uint8_t day)
 	uint16_t len = sizeof(bill_t);
 	uint16_t days = days_from_leap_year_begin(month, day);
 	uint32_t addr = DAY_BILL_START_ADDR + len * (days - 1);
+	///////////////////检查日期是否合法/////////////////////////////
+	if (CheckDateValid(year, month, day, 0, 0, 0) == 0)
+		return;
+	///////////////////检查是否存有相同的记录 有就加上/////////////////////////////
+	uint8_t ret;
+	ret = get_day_used_bill(year, month, day, &day_bill);
+	if (ret == 0) // 数据合法,且年月日都相同
+	{
+		fw_used = day_bill.fw_used;
+		bw_used = day_bill.bw_used;
+	}
+	else
+	{
+		fw_used = 0;
+		bw_used = 0;
+	}
+	////////////////////////////////////////////////////////////////////////////////
 
-	fw_used = get_day_fw_used_bill();
-	bw_used = get_day_bw_used_bill();
+	fw_used += get_day_fw_used_bill();
+	bw_used += get_day_bw_used_bill();
 
 	day_bill.flag = 1;
 	day_bill.date[0] = year;
@@ -204,20 +238,32 @@ void set_hour_used_bill(uint8_t year, uint8_t month, uint8_t day, uint8_t hour)
 	hour_bill_t hour_bill;
 	uint16_t len = sizeof(hour_bill_t);
 	uint32_t addr = HOUR_BILL_START_ADDR + HOUR_BILL_INDEX(day, hour) * len;
+	/////////////////////////////////检查时间是否合法///////////////////////////////////////
+	if (CheckDateValid(year, month, day, hour, 0, 0) == 0)
+		return; // 时间不合法
+	/////////////////////////如果记录中存在相同日期的数据,则累加//////////////////////
+
+	uint8_t ret;
+	ret = get_hour_used_bill(year, month, day, hour, &hour_bill);
+	if (ret == 0) // 数据合法且日期相同
+	{
+		fw_used = hour_bill.fw_used[0] + ((uint32_t)hour_bill.fw_used[1] << 8) + ((uint32_t)hour_bill.fw_used[2] << 16);
+		bw_used = hour_bill.bw_used[0] + ((uint32_t)hour_bill.bw_used[1] << 8) + ((uint32_t)hour_bill.bw_used[2] << 16);
+		fr = hour_bill.flow_rate[0] + ((uint32_t)hour_bill.flow_rate[1] << 8) + ((uint32_t)hour_bill.flow_rate[2] << 16);
+	}
+	else
+	{
+		fw_used = 0;
+		bw_used = 0;
+		fr = 0;
+	}
+	//////////////////////////////////////////////////////////////////////////////
 
-	fw_used = get_hour_fw_used_bill();
-	bw_used = get_hour_bw_used_bill();
+	fw_used += get_hour_fw_used_bill();
+	bw_used += get_hour_bw_used_bill();
 
-	fr = (uint32_t)get_flow_rate_bill();
+	fr = (uint32_t)get_flow_rate_bill() > fr ? (uint32_t)get_flow_rate_bill() : fr;
 
-#ifdef DEBUG_BILL2
-	// fw_used = hour;
-	// bw_used = 2 * hour;
-	// fr = 3 * hour;
-#endif
-#ifdef DEBUG_BILL
-	LOG("%d-%d-%d %d write hour bill fw= %d\r\n", year, month, day, hour, fw_used);
-#endif
 	memset(&hour_bill, 0, sizeof(hour_bill_t));
 
 	hour_bill.flag = 1;
@@ -261,15 +307,33 @@ void set_5min_used_bill(uint8_t year, uint8_t month, uint8_t day, uint8_t hour,
 	hour_bill_t bill;
 	uint16_t len = sizeof(hour_bill_t);
 	uint32_t addr = FIVE_MIN_BILL_START_ADDR + len * FIVE_MIN_BILL_INDEX(day, hour, minute);
+	/////////////////////////////////检查时间是否合法///////////////////////////////////////
+	if (CheckDateValid(year, month, day, hour, minute, 0) == 0)
+		return;
+	////////////////////////////////////////////////////////////////////////////////////////
+	uint8_t ret;
+	ret = get_5min_used_bill(year, month, day, hour, minute, &bill);
+	if (ret == 0)
+	{
+		fw_used = bill.fw_used[0] + ((uint32_t)bill.fw_used[1] << 8) + ((uint32_t)bill.fw_used[2] << 16);
+		bw_used = bill.bw_used[0] + ((uint32_t)bill.bw_used[1] << 8) + ((uint32_t)bill.bw_used[2] << 16);
+		fr = bill.flow_rate[0] + ((uint32_t)bill.flow_rate[1] << 8) + ((uint32_t)bill.flow_rate[2] << 16);
+	}
+	else
+	{
+		fw_used = 0;
+		bw_used = 0;
+		fr = 0;
+	}
+	////////////////////////////////////////////////////////////////////////////////////////
+
+	fw_used += get_5min_fw_used_bill();
+	bw_used += get_5min_bw_used_bill();
+	fr = (uint32_t)get_flow_rate_bill() > fr ? (uint32_t)get_flow_rate_bill() : fr;
+
+	////////////////////////////////////////////////////////////////////////////////////////
+	bill.date[0] = year;
 
-	fw_used = get_5min_fw_used_bill();
-	bw_used = get_5min_bw_used_bill();
-	fr = (uint32_t)get_flow_rate_bill();
-#ifdef DEBUG_BILL2
-	fw_used = minute * 10;
-	bw_used = minute * 20;
-	fr = minute * 5;
-#endif
 	bill.flag = 1;
 	bill.date[0] = year;
 	bill.date[1] = month; // num保存该小时内第几个5分钟数据
@@ -359,21 +423,7 @@ void save_cur_flow_bill(void)
 uint8_t get_month_used_bill(uint8_t year, uint8_t month, bill_t *bill)
 {
 
-	rtc_run_t *rr;
-	get_rtc_run(&rr);
-	int16_t ms = (rr->year * 12 + rr->month) - (year * 12 + month);
-
 	memset(bill, 0, sizeof(bill_t));
-	if (ms <= 0 || ms > MONTH_BILL_NUM)
-	{
-		// #ifdef DEBUG_BILL2
-		//			LOG("month date out\r\n");
-		// #endif
-		return 0; // 超出48个月
-	}
-	// #ifdef DEBUG_BILL2
-	//			LOG("month date ok\r\n");
-	// #endif
 	uint16_t len = sizeof(bill_t);
 	uint32_t addr = MONTH_BILL_START_ADDR + len * MONTH_BILL_INDEX(year, month);
 	uint8_t ret;
@@ -458,11 +508,11 @@ int32_t get_days_between_now(uint8_t y2, uint8_t m2, uint8_t d2)
 	return days1 - days2;
 }
 //////////////////读取指定时间的日使用量//////////////////////////
-uint8_t get_day_used_bill(uint8_t month, uint8_t day, bill_t *bill)
+uint8_t get_day_used_bill(uint8_t year, uint8_t month, uint8_t day, bill_t *bill)
 {
 
 	uint16_t days = days_from_leap_year_begin(month, day);
-	uint16_t len = sizeof(bill_t);
+	uint16_t len = sizeof(bill_t); // 16
 	uint32_t addr = DAY_BILL_START_ADDR + len * (days - 1);
 #ifdef DEBUG_BILL2
 	LOG("%d-%d\r\n", month, day);
@@ -472,7 +522,7 @@ uint8_t get_day_used_bill(uint8_t month, uint8_t day, bill_t *bill)
 	uint8_t ret = read_eeprom(addr, (uint8_t *)bill, len);
 	if (ret != 0)
 		return ret;
-	if (bill->date[1] != month || bill->date[2] != day)
+	if (bill->date[0] != year || bill->date[1] != month || bill->date[2] != day)
 		return 1;
 	return 0;
 }
@@ -489,7 +539,7 @@ int32_t get_hours_between_now(uint8_t year, uint8_t month, uint8_t day, uint8_t
 }
 
 ///////////////读取指定时间的小时使用量//////////////////////////
-uint8_t get_hour_used_bill(uint8_t day, uint8_t hour, hour_bill_t *bill)
+uint8_t get_hour_used_bill(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, hour_bill_t *bill)
 {
 	uint16_t len = sizeof(hour_bill_t);
 	uint32_t addr = HOUR_BILL_START_ADDR + HOUR_BILL_INDEX(day, hour) * len;
@@ -497,19 +547,29 @@ uint8_t get_hour_used_bill(uint8_t day, uint8_t hour, hour_bill_t *bill)
 
 	// int32_t hours = get_hours_between_now(year,month,day,hour);
 	// if(hours <= 0 || hours > 31 * 24)return 0;
-
-	return read_eeprom(addr, (uint8_t *)bill, len);
+	uint8_t ret;
+	ret = read_eeprom(addr, (uint8_t *)bill, len);
+	if (ret != 0)
+		return ret;
+	if (bill->date[0] != year || bill->date[1] != month || bill->date[2] != day || bill->date[3] != hour)
+		return 1;
+	return 0;
 }
 
 //////////////////读取指定时间的5分钟使用量////////////////////////////
-uint8_t get_5min_used_bill(uint8_t day, uint8_t hour, uint8_t minute, hour_bill_t *bill)
+uint8_t get_5min_used_bill(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, hour_bill_t *bill)
 {
 	uint16_t len = sizeof(hour_bill_t);
 	uint32_t addr = FIVE_MIN_BILL_START_ADDR + len * FIVE_MIN_BILL_INDEX(day, hour, minute);
 
 	memset(bill, 0, sizeof(hour_bill_t));
-
-	return read_eeprom(addr, (uint8_t *)bill, len);
+	uint8_t ret;
+	ret = read_eeprom(addr, (uint8_t *)bill, len);
+	if (ret != 0)
+		return ret;
+	if (bill->date[0] != year || bill->date[1] != month || bill->date[2] != day || bill->date[3] != hour)
+		return 1;
+	return 0;
 }
 
 ////////////数据累加和校验生成///////////////////////
@@ -850,6 +910,10 @@ tm_t prev_hour(tm_t *date)
 	ndate.year = (uint8_t)(sdate >> 16);
 	return ndate;
 }
+/**
+ * 获取当前流量数据并更新账单信息
+ * @param ntm 指向时间结构体的指针,包含年、月、日、时、分等信息
+ */
 void get_cur_flow_data(tm_t *ntm)
 {
 	if (global_settle_flag != 0) // 在设置更新的底读之前,先进行结算
@@ -914,16 +978,11 @@ void app_bill_run(void)
 	if (bak_month_cum_flow.date[0] != ntm.year || bak_month_cum_flow.date[1] != ntm.month)
 	{
 		// 计算上个月的最后一天
-		ndate = (ntm.year << 16) | (ntm.month << 8) | 1; // 当前月1号
-		ndate = prev_day(ndate);						 // 回退一天,即上个月最后一天
-
-		// 存储上个月的使用量,时间戳为上个月最后一天
-		// if ((uint8_t)(ndate >> 16) == bak_month_cum_flow.date[0] && (uint8_t)(ndate >> 8) == bak_month_cum_flow.date[1])
-		if ((ndate >> 8) >= ((bak_month_cum_flow.date[0] << 8) | bak_month_cum_flow.date[1]))
-		{ // 结算月份必须大于等于备份月份
-			set_month_used_bill((uint8_t)(ndate >> 16), (uint8_t)(ndate >> 8), (uint8_t)(ndate));
-		}
-		// 更新备份:将当前累积流量保存为新的月度起始基准
+		//	ndate = (ntm.year << 16) | (ntm.month << 8) | 1; // 当前月1号
+		//	ndate = prev_day(ndate);						 // 回退一天,即上个月最后一天
+		set_month_used_bill(bak_month_cum_flow.date[0], bak_month_cum_flow.date[1], bak_month_cum_flow.date[2]);
+		// 使用备份的日期进行存储,无论是自然过度到第二月还是修改日期到新的月份,数据始终保存到老月份去
+		//  更新备份:将当前累积流量保存为新的月度起始基准
 		set_month_cur_flow_bill();
 #ifdef DEBUG_BILL
 		LOG("%d-%d-%d write month bill\r\n", (uint8_t)(ndate >> 16), (uint8_t)(ndate >> 8), (uint8_t)(ndate));
@@ -936,15 +995,15 @@ void app_bill_run(void)
 	if (bak_day_cum_flow.date[0] != ntm.year || bak_day_cum_flow.date[1] != ntm.month || bak_day_cum_flow.date[2] != ntm.day)
 	{
 		// 计算昨天
-		ndate = (ntm.year << 16) | (ntm.month << 8) | ntm.day;
-		ndate = prev_day(ndate);
+		// ndate = (ntm.year << 16) | (ntm.month << 8) | ntm.day;
+		// ndate = prev_day(ndate);
 
 		// 存储昨天的使用量
 		// if ((uint8_t)(ndate >> 16) == bak_day_cum_flow.date[0] && (uint8_t)(ndate >> 8) == bak_day_cum_flow.date[1] && (uint8_t)(ndate) == bak_day_cum_flow.date[2])
-		if (ndate >= ((bak_day_cum_flow.date[0] << 16) | (bak_day_cum_flow.date[1] << 8) | bak_day_cum_flow.date[2]))
-		{ // 结算日期必须大于等于备份日期, 否则只更新基准,不记录使用量
-			set_day_used_bill((uint8_t)(ndate >> 16), (uint8_t)(ndate >> 8), (uint8_t)(ndate));
-		}
+		// if (ndate >= ((bak_day_cum_flow.date[0] << 16) | (bak_day_cum_flow.date[1] << 8) | bak_day_cum_flow.date[2]))
+		//{ // 结算日期必须大于等于备份日期, 否则只更新基准,不记录使用量
+		set_day_used_bill(bak_day_cum_flow.date[0], bak_day_cum_flow.date[1], bak_day_cum_flow.date[2]);
+		//}
 		// 更新备份:将当前累积流量保存为新的日度起始基准
 		set_day_cur_flow_bill();
 #ifdef DEBUG_BILL
@@ -957,34 +1016,34 @@ void app_bill_run(void)
 	if (bak_hour_cum_flow.date[0] != ntm.year || bak_hour_cum_flow.date[1] != ntm.month ||
 		bak_hour_cum_flow.date[2] != ntm.day || bak_hour_cum_flow.date[3] != ntm.hour)
 	{
-		tm_t prev_h_tm;
+		// tm_t prev_h_tm;
 
 		// 计算上一个小时的时间,用于存入记录的数据头(表示该小时结束的时间点或归属)
 		// 注意:不要直接修改 ntm,而是使用临时变量
-		prev_h_tm = ntm;
-		if (prev_h_tm.hour == 0)
-		{
-			// 如果当前是0点,上一个小时是昨天的23点
-			uint32_t prev_day_date = (prev_h_tm.year << 16) | (prev_h_tm.month << 8) | prev_h_tm.day;
-			prev_day_date = prev_day(prev_day_date);
-			prev_h_tm.year = (uint8_t)(prev_day_date >> 16);
-			prev_h_tm.month = (uint8_t)(prev_day_date >> 8);
-			prev_h_tm.day = (uint8_t)(prev_day_date);
-			prev_h_tm.hour = 23;
-		}
-		else
-		{
-			prev_h_tm.hour--;
-		}
+		// prev_h_tm = ntm;
+		// if (prev_h_tm.hour == 0)
+		// {
+		// 	// 如果当前是0点,上一个小时是昨天的23点
+		// 	uint32_t prev_day_date = (prev_h_tm.year << 16) | (prev_h_tm.month << 8) | prev_h_tm.day;
+		// 	prev_day_date = prev_day(prev_day_date);
+		// 	prev_h_tm.year = (uint8_t)(prev_day_date >> 16);
+		// 	prev_h_tm.month = (uint8_t)(prev_day_date >> 8);
+		// 	prev_h_tm.day = (uint8_t)(prev_day_date);
+		// 	prev_h_tm.hour = 23;
+		// }
+		// else
+		// {
+		// 	prev_h_tm.hour--;
+		// }
 
 		// 存储上一个小时的使用量
-		uint32_t baklong = ((bak_hour_cum_flow.date[0] << 24) | (bak_hour_cum_flow.date[1] << 16) | (bak_hour_cum_flow.date[2] << 8) | (bak_hour_cum_flow.date[3]));
-		uint32_t prevlong = ((prev_h_tm.year << 24) | (prev_h_tm.month << 16) | (prev_h_tm.day << 8) | (prev_h_tm.hour));
+		// uint32_t baklong = ((bak_hour_cum_flow.date[0] << 24) | (bak_hour_cum_flow.date[1] << 16) | (bak_hour_cum_flow.date[2] << 8) | (bak_hour_cum_flow.date[3]));
+		// uint32_t prevlong = ((prev_h_tm.year << 24) | (prev_h_tm.month << 16) | (prev_h_tm.day << 8) | (prev_h_tm.hour));
 		// if (bak_hour_cum_flow.date[0] == prev_h_tm.year && bak_hour_cum_flow.date[1] == prev_h_tm.month && bak_hour_cum_flow.date[2] == prev_h_tm.day && bak_hour_cum_flow.date[3] == prev_h_tm.hour)
-		if (baklong <= prevlong)
-		{ // 备份的时间必须早于当前时间的上一个小时,才记录时结数据
-			set_hour_used_bill(prev_h_tm.year, prev_h_tm.month, prev_h_tm.day, prev_h_tm.hour);
-		}
+		// if (baklong <= prevlong)
+		//{ // 备份的时间必须早于当前时间的上一个小时,才记录时结数据
+		set_hour_used_bill(bak_hour_cum_flow.date[0], bak_hour_cum_flow.date[1], bak_hour_cum_flow.date[2], bak_hour_cum_flow.date[3]);
+		//}
 		// 更新备份:将当前累积流量保存为新的小时起始基准
 		set_hour_cur_flow_bill();
 		// #ifdef DEBUG_BILL
@@ -997,18 +1056,18 @@ void app_bill_run(void)
 		bak_5min_cum_flow.date[2] != ntm.day || bak_5min_cum_flow.date[3] != ntm.hour ||
 		bak_5min_cum_flow.date[4] / 5 != ntm.min / 5)
 	{
-		tm_t bak_t;
-		bak_t.year = bak_5min_cum_flow.date[0];
-		bak_t.month = bak_5min_cum_flow.date[1];
-		bak_t.day = bak_5min_cum_flow.date[2];
-		bak_t.hour = bak_5min_cum_flow.date[3];
-		bak_t.min = bak_5min_cum_flow.date[4];
+		// tm_t bak_t;
+		// bak_t.year = bak_5min_cum_flow.date[0];
+		// bak_t.month = bak_5min_cum_flow.date[1];
+		// bak_t.day = bak_5min_cum_flow.date[2];
+		// bak_t.hour = bak_5min_cum_flow.date[3];
+		// bak_t.min = bak_5min_cum_flow.date[4];
 
 		// tm_t prev_5min_tm = get_prev_5min_tm(bak_t);
-		if (datecmp(bak_t, ntm) < 0) // 备份时间小于当前时间,则记录使用量
-		{
-			set_5min_used_bill(ntm.year, ntm.month, ntm.day, ntm.hour, ntm.min);
-		}
+		// if (datecmp(bak_t, ntm) < 0) // 备份时间小于当前时间,则记录使用量
+		//{
+		set_5min_used_bill(bak_5min_cum_flow.date[0], bak_5min_cum_flow.date[1], bak_5min_cum_flow.date[2], bak_5min_cum_flow.date[3], bak_5min_cum_flow.date[4]);
+		//}
 		set_5min_cur_flow_bill();
 #ifdef DEBUG_BILL
 		LOG("%d-%d-%d %d:%d write 5min bill\r\n", ntm.year, ntm.month, ntm.day, ntm.hour, ntm.min);
@@ -1209,10 +1268,10 @@ extern void clr_max_flow_rate_all(void);
 void clear_all_record(void)
 {
 	// 定义单次写入块大小 (128字节效率较高且栈安全)
-	clear_bottom_data();
+	clear_bottom_data();	 // 底读设置为0,并保存
 	clr_max_flow_rate_all(); // 清最高瞬时流量
-	clr_bill_struct_data();
-
+	clr_bill_struct_data();	 // 清除日结,月结等所有结算数据的基准累积量
+							 // 下面是清除所有结算数据
 #define CLEAR_BLOCK_SIZE 128
 	uint8_t dat[CLEAR_BLOCK_SIZE];
 	memset(dat, 0xFF, CLEAR_BLOCK_SIZE);
@@ -1399,8 +1458,18 @@ void clr_bill_struct_data(void)
 	memset(&bak_month_cum_flow, 0, sizeof(bak_month_cum_flow));
 	memset(&bak_day_cum_flow, 0, sizeof(bak_day_cum_flow));
 	memset(&bak_hour_cum_flow, 0, sizeof(bak_hour_cum_flow));
+	memset(bak_5min_cum_flow.date, 0, 6);
 	bak_5min_cum_flow.fw_cum_flow = 0;
 	bak_5min_cum_flow.bw_cum_flow = 0;
 	cum_flow_index.bw = 0;
 	cum_flow_index.fw = 0;
+}
+//// 检查日期是否有效
+uint8_t CheckDateValid(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
+{
+	if (year >= 100 || month == 0 || month > 12 || day == 0 || day > 31 || hour > 23 || min > 59 || sec > 59)
+		return 0;
+	if (day > monthday[month - 1] + ((year % 4 == 0 && month == 2) ? 1 : 0))
+		return 0;
+	return 1;
 }

+ 13 - 10
Users/bill/bill.h

@@ -34,16 +34,16 @@ extern "C"
 #define PRE_5MIN_COW_BAK_ADDR 0x1ac60
 #define COW_BAK_DATA_SIZE 32
 
-#define BAK_5MIN_NUM 16
+#define BAK_5MIN_NUM 8
 #define BAK_5MIN_SIZE 32
 
 //////兼容以前的函数名///////////////
 #define SetBillCumFlow set_cur_flow_bill
 #define SetBillVol set_flow_rate_bill
-#define read_day_bill get_day_used_bill
-#define read_month_bill get_month_used_bill
-#define read_hour_bill get_hour_used_bill
-#define read_five_min_bill get_5min_used_bill
+    // #define read_day_bill get_day_used_bill
+    // #define read_month_bill get_month_used_bill
+    // #define read_hour_bill get_hour_used_bill
+    // #define read_five_min_bill get_5min_used_bill
     /////////////////////////////////////////////
 
     typedef struct
@@ -171,10 +171,10 @@ extern "C"
     extern void set_5min_used_bill(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute);
     extern void set_cur_flow_bill(double cum, double fw_cum, double bw_cum);
 
-    extern uint8_t get_hour_used_bill(uint8_t day, uint8_t hour, hour_bill_t *bill);
-    extern uint8_t get_day_used_bill(uint8_t month, uint8_t day, bill_t *bill);
+    extern uint8_t get_hour_used_bill(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, hour_bill_t *bill);
+    extern uint8_t get_day_used_bill(uint8_t year, uint8_t month, uint8_t day, bill_t *bill);
     extern uint8_t get_month_used_bill(uint8_t year, uint8_t month, bill_t *bill);
-    extern uint8_t get_5min_used_bill(uint8_t day, uint8_t hour, uint8_t minute, hour_bill_t *bill);
+    extern uint8_t get_5min_used_bill(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, hour_bill_t *bill);
 
     extern uint8_t CheckTime(uint8_t *);
     extern uint8_t Sum8(uint8_t *, uint16_t);
@@ -193,7 +193,7 @@ extern "C"
     extern double FlowVol;
     extern void Debug_bill(void);
     // extern uint8_t init_month_cum_flow(void);
-    extern void clr_bill_struct_data(void);
+
     extern const uint8_t monthday[12];
     extern int8_t SetRtcTime(tm_t *);
     extern unsigned char save_cur_flow_flag; // 置1触发保存当前累计量
@@ -202,9 +202,12 @@ extern "C"
     extern void clear_all_record(void); // 清除所有记录
     extern void clear_log(void);        // 清除log
     extern void clear_bottom_data(void);
+    // extern void get_cur_flow_data(void);
     extern void get_cur_flow_data(tm_t *);
-    extern uint8_t global_settle_flag;
+    extern uint8_t CheckDateValid(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec);
     extern uint8_t StartUp;
+    extern uint8_t global_settle_flag;
+    extern void clr_bill_struct_data(void); // 清除账单结构体数据
 #ifdef DEBUG_BILL
     extern void verify_clear_operations(void);
 #endif

+ 96 - 66
Users/param/param.c

@@ -93,8 +93,14 @@ uint8_t eeprom_MassRead(uint8_t *dat, uint32_t addr, uint16_t len)
 	return ret;
 }
 
-#define DEFAULT_PATH_SKEW 0					// 超声波通道偏差修正系数
-#define DEFAULT_PIPE_COE 0.1168745			// COE系数
+#define DEFAULT_PATH_SKEW 0 // 超声波通道偏差修正系数
+
+#if VER_MODULE == 3
+#define DEFAULT_PIPE_COE 2.288299 // COE系数
+#else
+#define DEFAULT_PIPE_COE 0.1168745 // COE系数
+#endif
+
 #define DEFAULT_IMEI "000000000000000"		// 默认IMEI
 #define DEFAULT_CCID "00000000000000000000" // 默认IMEI
 //                     01234567890123456789
@@ -106,7 +112,8 @@ uint8_t eeprom_MassRead(uint8_t *dat, uint32_t addr, uint16_t len)
 void LoadDefaultParam(void) // 加载默认参数值
 {
 
-	memset((uint8_t *)&Paramx, 0, sizeof(Param_t));
+	// memset((uint8_t *)&Paramx, 0, sizeof(Param_t));
+	eeprom_MassRead((unsigned char *)&Paramx, PARAMX_START_ADDR, sizeof(Param_t)); // 读取参数
 	Paramx.path_skew[0] = DEFAULT_PATH_SKEW;
 	Paramx.path_skew[1] = DEFAULT_PATH_SKEW;
 	Paramx.path_skew[2] = DEFAULT_PATH_SKEW;
@@ -131,10 +138,13 @@ void LoadDefaultParam(void) // 
 	Paramx.dev_id[3] = 0x10;				  // bcd
 	Paramx.dev_id[4] = 0x00;				  // bcd
 	Paramx.dev_id[5] = 0x03;				  // bcd//设备地址 A0
-
+#if VER_MODULE == 3
+	Paramx.chan_num = 2;   // 超声波通道数量
+	Paramx.diameter = 100; // 直径
+#else
 	Paramx.chan_num = 1;  // 超声波通道数量
 	Paramx.diameter = 25; // 直径
-
+#endif
 	Paramx.pressure_sensor = 2; // without pressure sensor 是否带压力传感器,默认不带
 
 	Paramx.settlement_day = 0; // 结算日,默认 每月最后一天
@@ -158,16 +168,16 @@ void LoadDefaultParam(void) // 
 	Paramx.low_press_alarm_thres = 0;  // 低压力报警阈值
 
 	Paramx.main_server_ip[0] = 221;
-	Paramx.main_server_ip[1] = 229;
-	Paramx.main_server_ip[2] = 214;
-	Paramx.main_server_ip[3] = 202; // 主服务器ip地址
-	Paramx.main_server_port = 5683; // 主服务器端口号
+	Paramx.main_server_ip[1] = 236;
+	Paramx.main_server_ip[2] = 31;
+	Paramx.main_server_ip[3] = 231;	 // 主服务器ip地址
+	Paramx.main_server_port = 12001; // 主服务器端口号
 
 	Paramx.sub_server_ip[0] = 221; // 备用服务器ip地址
-	Paramx.sub_server_ip[1] = 229;
-	Paramx.sub_server_ip[2] = 214;
-	Paramx.sub_server_ip[3] = 202;
-	Paramx.sub_server_port = 5683; // 备用服务器端口号
+	Paramx.sub_server_ip[1] = 236;
+	Paramx.sub_server_ip[2] = 31;
+	Paramx.sub_server_ip[3] = 231;
+	Paramx.sub_server_port = 12001; // 备用服务器端口号
 
 	Paramx.dma_report_start[0] = 0;
 	Paramx.dma_report_start[1] = 0;
@@ -206,16 +216,17 @@ void LoadDefaultParam(void) // 
 	// 	*fp = 1;
 	// 	fp++;
 	// }
+	Paramx.b = 63;
+	Paramx.n = 45;
+	Paramx.q = 32;
+	Paramx.r = 500;
 	Paramx.q_value = CHECK_Q_VALUE; // 默认Q值,影响check脉冲计算
 	Paramx.para_len = sizeof(Paramx) - 8;
 	Paramx.para_crc32 = com_crc32L_next(0xFFFFFFFFu, (uint8_t *)(&Paramx) + 8, sizeof(Param_t) - 8, 0xEDB88320); // 计算crc校验值
 	// eeprom_MassWrite((uint8_t *)&Paramx,PARAMX_START_ADDR,sizeof(Param_t));
 	// eeprom_MassRead((uint8_t *)&Paramx,PARAMX_START_ADDR,sizeof(Param_t));
-	Paramx.b = 63;
-	Paramx.n = 45;
-	Paramx.q = 32;
-	Paramx.r = 500;
 	rewrite_para_flag |= 0x1;
+	Paramx.nb_band_flag = 0;
 }
 
 void get_para_to_tdcitf(void) // 获取参数给tdcItf
@@ -241,13 +252,7 @@ void get_para_to_tdcitf(void) // 
 	for (i = 0; i < MUX_CH_NUM; i++)
 		TdcItf.mux_ch_no[i] = Paramx.mux_ch_no[i];
 }
-// #define DEBUG_PARAM
 
-// #ifdef DEBUG_PARAM
-// uint8_t p1data[sizeof(Param_t)];
-// uint8_t p2data[sizeof(Param_t)];
-// uint8_t err_pos=0;
-// #endif
 void ParamInit(void) // 上电初始化
 {
 	uint8_t i;
@@ -258,9 +263,6 @@ void ParamInit(void) // 
 	}
 
 	eeprom_MassRead((unsigned char *)&Paramx, PARAMX_START_ADDR, sizeof(Param_t)); // 读取参数
-
-	// memcpy(p1data,&Paramx,sizeof(Param_t));
-
 	uint32_t crc = com_crc32L_next(0xFFFFFFFFu, (uint8_t *)(&Paramx) + 8, sizeof(Param_t) - 8, 0xEDB88320);
 
 	if (crc != Paramx.para_crc32) // wxl2026-5-8 校验错误时记录日志
@@ -269,6 +271,7 @@ void ParamInit(void) // 
 	if (Paramx.para_len != sizeof(Paramx) - 8)
 	{
 		LoadDefaultParam(); // 加载默认参数
+		rewrite_para_flag |= 4;
 	}
 	// Nb_Run_t *nb_run;
 	// GetNbRun(&nb_run);
@@ -281,12 +284,13 @@ void ParamInit(void) // 
 	// Paramx.ver_operator = VER_OPERATOR; // operator, 1: China Telecom;
 	// Paramx.ver_module = VER_MODULE;		// module, 1: HC32_BC28;
 	// Paramx.ver_firmware = VER_FIRMWARE; // firmware version;//设备版本信息
+#if VER_MODULE == 4
 	if (Paramx.chan_num != 1)
 	{
 		Paramx.chan_num = 1;
 		rewrite_para_flag |= 1;
 	}
-
+#endif
 	get_para_to_tdcitf(); // 获取参数到tdcitf结构体
 
 	memset((uint8_t *)&PatchInfo, 0, sizeof(PATCH_INFO_DEF));
@@ -326,10 +330,7 @@ void check_rewrite_para(void)
 	if (rewrite_para_flag & 0x4) // wxl2026-5-8
 	{
 		write_alarm(LOG_PARA_CRC_ERROR, 1, 5555);
-		//	memcpy(p2data,&Paramx,sizeof(Param_t));
 		set_crc_check_para();
-		//		int i;
-		///	for(i=0;i<sizeof(Param_t);i++)if(p1data[i]!=p2data[i])err_pos= i;
 	}
 
 	rewrite_para_flag = 0;
@@ -387,6 +388,7 @@ uint8_t CheckCValueIndex(uint16_t temp_idx, uint16_t spdLvl) {
 #endif
 
 #if 0
+// modified by yuewei 20260429 start
 uint8_t CheckCValueIndex(uint16_t temp_idx, uint16_t spdLvl)
 {
 	// 1. Boundary safety limit, only 3 temperature intervals, actually use index 0 only
@@ -408,7 +410,11 @@ uint8_t CheckCValueIndex(uint16_t temp_idx, uint16_t spdLvl)
 	for (i = 0; i < CHECK_POINT_NUM - 1; i++)
 	{
 		// Directly match speed level interval
+#if VER_MODULE == 3
+		if (spdLvl + 3 <= p->spd_lvl[i + 1])
+#else
 		if (spdLvl <= p->spd_lvl[i + 1])
+#endif
 		{
 			return i;
 		}
@@ -417,7 +423,10 @@ uint8_t CheckCValueIndex(uint16_t temp_idx, uint16_t spdLvl)
 	// 4. Greater than maximum speed level -> return last index
 	return CHECK_POINT_NUM - 1;
 }
+// modified by yuewei 20260429 end
 #endif
+
+// add by yuewei 20260731,输入的流速等级spd_lvl减5,吸附到接近的流速等级
 uint8_t CheckCValueIndex(uint16_t temp_idx, uint16_t spdLvl)
 {
 	// 1. 温度区间安全限界,仅0/1/2有效
@@ -797,7 +806,7 @@ int8_t get_server_ip_port_para(SERVER_IP_PORT_DEF *server_ip_para)
 	return 0;
 }
 ////////////////////////////设置定时上报周期和时间间隔/////////////////////////////////////////////////////
-//                                                                   参数:regular_report_para定时上报数据结构体,包含起始基准时间,间隔时间u\
+//                                                                        参数:regular_report_para定时上报数据结构体,包含起始基准时间,间隔时间u\
 //返回:1:成功2:失败
 /////////////////////////////////////////////////////////////////////////////////////////////////////////
 int8_t set_regular_report_para(REGULAR_REPORT_DEF *regular_report_para)
@@ -876,6 +885,20 @@ int8_t set_flow_alarm_para(FLOW_ALARM_PARA_DEF *flow_alarm_para)
 	}
 	return (ret == 0 ?: -1);
 }
+////////////////////////////设置nb已选择频段标志/////////////////////////////////
+int8_t set_nb_band(uint8_t band)
+{
+	uint8_t flag = 0, ret = 0;
+	uint8_t dat = 0;
+	// 判断数据是否在正常范围内
+	Paramx.nb_band_flag = band;
+	ret = set_para_if_nessary(&dat, &Paramx.nb_band_flag, 1, &flag); // 参数整体保存
+	if (flag == 1)
+	{ // 保存crc校验
+		ret |= set_crc_check_para();
+	}
+	return (ret == 0 ?: -1);
+}
 ////////////////////////获取流量告警参数值/////////////////////////////////////////
 // 参数flow_alarm_para 保存流量参数
 // 返回:1:成功 2:失败
@@ -978,7 +1001,7 @@ int8_t get_settlement_day_para(SETTLEMENT_DAY_DEF *settlement_day_para)
 ///////////////////////////////设置表端底读///////////////////////////////////////////////////
 // 参数:指向表端底读数据指针
 // 返回:1:成功 2:失败
-//////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////int8_t set_meter_bottom_data(METER_BOTTOM_DEF *bottom_data)
 int8_t set_meter_bottom_data(METER_BOTTOM_DEF *bottom_data)
 {
 	uint8_t flag = 0, ret = 0;
@@ -1065,10 +1088,9 @@ int8_t get_30day_record_data(uint8_t *data)
 	for (i = 0; i < 30; i++)
 	{
 		date = prev_day(date);
-		flag = get_day_used_bill((uint8_t)(date >> 8), (uint8_t)date, &bill);
+		flag = get_day_used_bill((uint8_t)(date >> 16), (uint8_t)(date >> 8), (uint8_t)date, &bill);
 		ret |= flag;
-		if ((uint8_t)(date >> 16) != bill.date[0] || (uint8_t)(date >> 8) != bill.date[1] || (uint8_t)(date & 0xff) != bill.date[2] // rec time is not  intend to read
-			|| flag != 0)
+		if (flag != 0)
 		{
 			ret |= 1;
 			for (j = 0; j < 12; j++)
@@ -1109,14 +1131,14 @@ int8_t get_hour_record_data(uint8_t year, uint8_t month, uint8_t day, uint8_t *d
 	memset(data, 0, 244);
 
 	// 2. 检查时间有效性
-	days = get_days_between_now(year, month, day);
+	// days = get_days_between_now(year, month, day);
 
 	// 假设:有效范围为过去30天内(含今天,即0~30天)
 	// 如果 get_days_between_now 返回负数表示未来,正数表示过去
-	if (days < 0 || days > 30)
-	{
-		return 0; // 不在30天内,返回全零(已memset)
-	}
+	// if (days < 0 || days > 30)
+	//{
+	//	return 0; // 不在30天内,返回全零(已memset)
+	//}
 
 	// 3. 读取数据
 	// 注意:请确认 get_hour_used_bill 的正确用法。
@@ -1132,10 +1154,10 @@ int8_t get_hour_record_data(uint8_t year, uint8_t month, uint8_t day, uint8_t *d
 		// 如果不能,你需要修改 get_hour_used_bill 或在此处提供完整日期上下文。
 
 		// 暂时沿用原调用方式,但加上注释警示
-		if (get_hour_used_bill(day, i, &bill) == 0)
+		if (get_hour_used_bill(year, month, day, i, &bill) == 0)
 		{
-			if (bill.date[0] != year || bill.date[1] != month || bill.date[2] != day || bill.date[3] != i) // if rec time is not valid drop it
-				continue;
+			// if (bill.date[0] != year || bill.date[1] != month || bill.date[2] != day || bill.date[3] != i) // if rec time is not valid drop it
+			//	continue;
 			data[0] = 0x14; // 标记有效? 原代码在循环外设置 data[0]=0x14, 这里如果部分失败怎么处理?
 							// 原代码逻辑:只要进入else,data[0]就被设为0x14。
 							// 如果某个小时失败,bill是全零,拷贝进去也是零。
@@ -1210,6 +1232,7 @@ int8_t get_5min_record_data(GET_5MIN_REOCORD_DEF *get_5min_record_info, uint16_t
 	start_time.day = get_5min_record_info->start_time[2];
 	start_time.hour = get_5min_record_info->start_time[3];
 	start_time.min = get_5min_record_info->start_time[4];
+	start_time.min = (start_time.min / 5) * 5;
 	start_time.sec = 0;
 
 	// 3. 计算当前页的起始查询时间
@@ -1226,25 +1249,20 @@ int8_t get_5min_record_data(GET_5MIN_REOCORD_DEF *get_5min_record_info, uint16_t
 	for (i = 0; i < 24; i++)
 	{
 		// 【关键修正】:因为底层存储使用“区间末尾时间”作为标记
-		// 所以查询 10:00 的数据,实际要用 10:05 去查
 		memcpy(&index_time, &query_time, sizeof(tm_t));
-		time_add_secs(&index_time, &index_time, 5 * 60);
+		// time_add_secs(&index_time, &index_time, 5 * 60);
 
 		// 5. 调用底层读取函数
 		// 使用 index_time (末尾时间) 进行查询
 		// 【严重警告】:请确认 get_5min_used_bill 能正确处理 index_time 的年月!
 		// 如果它只能处理当前月,查询历史数据必错。
-		uint8_t flag = get_5min_used_bill(index_time.day, index_time.hour, index_time.min, &bill);
+		uint8_t flag = get_5min_used_bill(index_time.year, index_time.month, index_time.day, index_time.hour, index_time.min, &bill);
 
 		if (flag != 0)
 		{
 			// 读取失败,该点数据保持为 0
 			ret |= 1;
 		}
-		else if (bill.date[0] != index_time.year || bill.date[1] != index_time.month || bill.date[2] != index_time.day || bill.date[3] != index_time.hour)
-		{
-			ret |= 1;
-		}
 		else
 		{
 			// 填充数据
@@ -1299,19 +1317,20 @@ int8_t get_log_record(uint8_t start, uint8_t num, uint8_t *data)
 /////////////////////////////设置声道数/////////////////////////////////////////////
 int8_t set_channel_numb(uint8_t *numb)
 {
-	/*
 	if (*numb == 0 || *numb > 4)
 		return -2;
 	uint8_t flag = 0, ret = 0;
 	// 判断数据是否在正常范围内
+	// add clear blank flag wxl 2026-5-21
+	TdcItf.blank_flag = 0;
+	set_mux_ch(0);
+
 	ret = set_para_if_nessary(numb, &Paramx.chan_num, 1, &flag); // 参数整体保存
 	if (flag == 1)
 	{ // 保存crc校验
 		ret |= set_crc_check_para();
 	}
 	return (ret == 0 ? 0 : -1);
-	*/
-	return 0;
 }
 ////////////////////////////////读表地址/////////////////////////////////////////////////
 int8_t get_device_addr(uint8_t *data)
@@ -1435,6 +1454,23 @@ int8_t get_quad_cell_data(void *quad_cell_data)
 ////////////////////// 判断温度补偿数据是否合法////////////////////////////////
 // 合法返回 0, 不合法返回-1
 //////////////////////////////////////////////////////
+#if VER_MODULE == 3
+int8_t Check_quad_cell_data_valid(uint32_t quad_cell_addr)
+{
+	// float temp[4];
+	Quad_Cell_t temp;
+	uint8_t i;
+	for (i = 0; i < Quad_Cell_NUM; i++)
+	{
+		eeprom_MassRead((uint8_t *)&temp, (uint32_t)quad_cell_addr + i * sizeof(Quad_Cell_t), sizeof(Quad_Cell_t));
+		if (temp.value < -100 || temp.value > 500000 ||
+			temp.coe.m < -100 || temp.coe.m > 500000 ||
+			temp.coe.k < -100 || temp.coe.k > 500000)
+			return -1;
+	}
+	return 0;
+}
+#else
 int8_t Check_quad_cell_data_valid(uint32_t quad_cell_addr)
 {
 	float temp[4];
@@ -1450,6 +1486,7 @@ int8_t Check_quad_cell_data_valid(uint32_t quad_cell_addr)
 	}
 	return 0;
 }
+#endif
 
 ///////////////////////设置自动匹配电平参数///////////////////////////////////////////////
 // 参数指针data 包含比较器和比较器门槛和门槛宽度
@@ -1477,19 +1514,7 @@ int8_t set_skew_para(SKEW_PARA_DEF *skew_para)
 	}
 	return (ret == 0 ? 0 : -1);
 }
-////////////////////////////设置nb已选择频段标志/////////////////////////////////
-int8_t set_nb_band(void)
-{
-	uint8_t flag = 0, ret = 0;
-	uint8_t dat = 0;
-	// 判断数据是否在正常范围内
-	ret = set_para_if_nessary(&dat, &Paramx.nb_band_flag, 1, &flag); // 参数整体保存
-	if (flag == 1)
-	{ // 保存crc校验
-		ret |= set_crc_check_para();
-	}
-	return (ret == 0 ?: -1);
-}
+
 ////////////////////////////读取自动匹配电平参数/////////////////////////////////////////////
 // 参数指针保存比较器和比较器门槛宽度数据
 // 返回1读取成功
@@ -1534,6 +1559,11 @@ uint16_t pack_crc_check(uint16_t prev_data, uint8_t *data, uint16_t len)
 uint8_t rtc_1s_flag;
 void run_clk_task_handler(void)
 {
+#ifdef LED_DEF
+	rtc_run_t *rr;
+	get_rtc_run(&rr);			  // 获取当前时间
+	SetLed(LED1, rr->second % 2); // 1秒闪烁
+#endif
 	check_rewrite_para(); // 相关参数判断,不合法的重写eeprom
 	rtc_1s_flag = 1;
 }

+ 12 - 12
Users/param/param.h

@@ -10,11 +10,11 @@
 #endif
 
 #ifndef Q1
-#define Q1 (0.0126f) //modified by yuewei 20260610 0.2f->0.0126f
+#define Q1 (0.0126f) // modified by yuewei 20260610 0.2f->0.0126f
 #endif
 
 #ifndef Q3
-#define Q3 (6.3f) //modified by yuewei 20260610 100->6.3f
+#define Q3 (6.3f) // modified by yuewei 20260610 100->6.3f
 #endif
 
 #ifndef CHECK_Q_VALUE
@@ -69,19 +69,19 @@ typedef struct
 {
 	uint32_t para_len;
 	uint32_t para_crc32;
-	float path_skew[4];	  // 偏差修正系数
-	float pipe_coe;		  // coe系数
-	//char imei[16];		  // 设备imei号
-	//char ccid[32];		  // 设备ccid号
+	float path_skew[4]; // 偏差修正系数
+	float pipe_coe;		// coe系数
+	// char imei[16];		  // 设备imei号
+	// char ccid[32];		  // 设备ccid号
 	uint8_t mux_ch_no[4]; // 多路通道地址
 
 	uint8_t dev_id[DEV_ID_LEN]; // 设备地址,6字节
 	uint8_t reserved1[2];		// 保留 4字节对齐
 
-//	uint8_t ver_type;	  // 水表类型
-//	uint8_t ver_operator; // 运营商
-//	uint8_t ver_module;	  // 模组
-//	uint8_t ver_firmware; // 软件版本号
+	//	uint8_t ver_type;	  // 水表类型
+	//	uint8_t ver_operator; // 运营商
+	//	uint8_t ver_module;	  // 模组
+	//	uint8_t ver_firmware; // 软件版本号
 
 	uint16_t diameter;		 // 直径
 	uint8_t chan_num;		 // 超声波通道数
@@ -139,7 +139,7 @@ typedef struct
 	uint16_t b; // n始动值
 	uint16_t q; // q值
 	uint16_t r; // 量程比
-		uint8_t nb_band_flag;
+	uint8_t nb_band_flag;
 } Param_t;
 
 typedef struct
@@ -350,7 +350,7 @@ extern const char SOFT_VER[5];
 extern uint8_t rewrite_para_flag;
 extern void check_rewrite_para(void);
 extern void run_clk_task_handler(void);
-extern int8_t set_nb_band(void);
+extern int8_t set_nb_band(uint8_t band);
 // extern Quad_Cell_t Quad_Cell_Ary[];
 
 #endif