#include "billing.h" #include "sundry.h" #include "string.h" #include "system_parameter.h" #include "main.h" #include "system_log.h" double yesterday_cumulate_sc = 0; uint8_t no_use_gas_days_cnt = 0; ErrorStatus_STM32 have_gprs_send_flag = ERROR_1; uint8_t no_gprs_days_cnt = 0; BILLING_REAL_PARA_T billing_real_para_g = { .price_type_mode_now = 0, .price_now = 10000, // ĬÈϵ¥¼Û ·Å´ó10000±¶ .balance_now = 10.0f // ĬÈÏÓà¶î }; TYPE_CHECK_SIZE(BILLING_ALARM_CFG_T,39);//ºË²é½á¹¹Ìå´óС BILLING_ALARM_CFG_T billing_alarm_cfg_g = { .balance_small_value = {10000, 5000, 0, -5000, -10000}, //·Å´ó100±¶ .cumulate_flow_value = 0, .no_gprs_days = 5, .no_use_gas_days = 7}; TYPE_CHECK_SIZE(LADDER_PRICE_CFG_PARA_T,111);//ºË²é½á¹¹Ìå´óС LADDER_PRICE_CFG_PARA_T ladder_price_cfg_para_true_g = { .price_ver = LADDER_PRICE_DEFAULT_VER, .normal_price_now = 10000, .set_price_type_mode = SPM_NORMAL, .period_state = PPS_CYCLICALLY, .period_start_time = {0x22, 0x11, 0x01, 0, 0, 0}, .period_unit = PPU_DAY, .period_duration = 30, .set_ladder_price = {35000, 40000, 50000, 60000, 70000}, .set_ladder_cumulate = {500, 1000, 1500, 2000, 2500}, .set_time_price[0] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0}, .set_time_price[1] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0}, .set_time_price[2] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0}, .set_time_price[3] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0}, .set_time_price[4] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0}, .time_unit = PPU_DAY, .price_scheme_start_time = {0x22, 0x11, 0x01, 0, 0, 0}, }; LADDER_PRICE_CFG_PARA_T ladder_price_cfg_para_new_g = { .price_ver = LADDER_PRICE_DEFAULT_VER, .normal_price_now = 10000, .set_price_type_mode = SPM_NORMAL, .period_state = PPS_CYCLICALLY, .period_start_time = {0x22, 0x11, 0x01, 0, 0, 0}, .period_unit = PPU_DAY, .period_duration = 30, .set_ladder_price = {35000, 40000, 50000, 60000, 70000}, .set_ladder_cumulate = {500, 1000, 1500, 2000, 2500}, .set_time_price[0] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0}, .set_time_price[1] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0}, .set_time_price[2] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0}, .set_time_price[3] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0}, .set_time_price[4] = {.time = {0x22, 0x11, 0x01, 0, 0, 0}, .duration = 0}, .time_unit = PPU_DAY, .price_scheme_start_time = {0x22, 0x11, 0x01, 0, 0, 0}, }; /*¼ÆÁ¿Êý¾Ý״̬/±¨¾¯×Ö´¦Àí*/ void State_Alarm_Bytes_BillingDataHandler(double balance, BILLING_ALARM_CFG_T *billing_alarm_cfg_p) { if (balance > (billing_alarm_cfg_p->balance_small_value[0] * 0.01f)) // 100 ~ ÕýÎÞÇî { __SYS_STATUS_BYTES_STATUS(balance_small_1, RESET, AV_BALANCE_1); __SYS_STATUS_BYTES_STATUS(balance_small_2, RESET, AV_BALANCE_2); __SYS_STATUS_BYTES_STATUS(balance_small_3, RESET, AV_BALANCE_3); __SYS_STATUS_BYTES_STATUS(balance_small_4, RESET, AV_BALANCE_4); } else if (balance > (billing_alarm_cfg_p->balance_small_value[1] * 0.01f)) // 50~100 __SYS_STATUS_ALARM_BYTES_SET(balance_small_1); else if (balance > (billing_alarm_cfg_p->balance_small_value[2] * 0.01f)) // 0~50 { __SYS_STATUS_ALARM_BYTES_SET(balance_small_1); __SYS_STATUS_ALARM_BYTES_SET(balance_small_2); } else if (balance > (billing_alarm_cfg_p->balance_small_value[3] * 0.01f)) // -50~0 { __SYS_STATUS_ALARM_BYTES_SET(balance_small_1); __SYS_STATUS_ALARM_BYTES_SET(balance_small_2); __SYS_STATUS_ALARM_BYTES_SET(balance_small_3); } else // if (balance > (billing_alarm_cfg_p->balance_small_value[4] * 0.01f)) //-100 ~ -50 { __SYS_STATUS_ALARM_BYTES_SET(balance_small_1); __SYS_STATUS_ALARM_BYTES_SET(balance_small_2); __SYS_STATUS_ALARM_BYTES_SET(balance_small_3); __SYS_STATUS_ALARM_BYTES_SET(balance_small_4); } // else // ¸ºÎÞÇî ~ -100 // { // __SYS_STATUS_ALARM_BYTES_SET(balance_small_1); // __SYS_STATUS_ALARM_BYTES_SET(balance_small_2); // __SYS_STATUS_ALARM_BYTES_SET(balance_small_3); // __SYS_STATUS_ALARM_BYTES_SET(balance_small_4); // __SYS_STATUS_ALARM_BYTES_SET(balance_small_5); // } /*ÀÛ¼ÆÆøÁ¿µ½*/ if (billing_alarm_cfg_p->cumulate_flow_value != 0) { if (sys_realtime_data_g.measure_para_s.forward_cumulate_sc >= billing_alarm_cfg_p->cumulate_flow_value) { // Sys_Log_E2pParaWrite(cumulate_close_valve_flag,AV_SET_CUMULATE); __SYS_STATUS_ALARM_BYTES_SET(set_cumulate_up_to); } } } /*ÎÞÓÃÆø/Éϱ¨Êý¾Ý״̬/±¨¾¯×Ö´¦Àí*/ void State_Alarm_Bytes_NoGpra_NoGasHandler(BILLING_ALARM_CFG_T *billing_alarm_cfg_p) { if (DAILY_ZERO) // 0µã0·Ö0Ãë { /*ÎÞÓÃÆøÌìÊýµ½*/ if (billing_alarm_cfg_p->no_use_gas_days) { if (sys_realtime_data_g.measure_para_s.forward_cumulate_sc > yesterday_cumulate_sc) { yesterday_cumulate_sc = sys_realtime_data_g.measure_para_s.forward_cumulate_sc; no_use_gas_days_cnt = 0; __SYS_STATUS_BYTES_STATUS(no_use_gas_date_up_to, RESET, AV_NO_USE_GAS); } else { if (++no_use_gas_days_cnt >= billing_alarm_cfg_p->no_use_gas_days) __SYS_STATUS_ALARM_BYTES_SET(no_use_gas_date_up_to); } } /*ÎÞÉϱ¨ÌìÊýµ½*/ if (billing_alarm_cfg_p->no_gprs_days) { if (have_gprs_send_flag == SUCCESS_0) { have_gprs_send_flag = ERROR_1; no_gprs_days_cnt = 0; __SYS_STATUS_BYTES_STATUS(no_gprs_date_up_to, RESET, AV_NO_GPRS); } else { if (++no_gprs_days_cnt >= billing_alarm_cfg_p->no_gprs_days) __SYS_STATUS_ALARM_BYTES_SET(no_gprs_date_up_to); } } } } /*ʵʱ¼Æ·Ñ³ÌÐò * single_flow_sum£ºµ¥´ÎµÄÁ÷Á¿ºÍ */ void Billing_RealTimeProcess(BILLING_MODE_T start_flag, __IO double single_flow_sum, LADDER_PRICE_CFG_PARA_T *ladder_cfg_real_p, BILLING_REAL_PARA_T *billing_para_p) { if ((start_flag == BM_DEVICE || (start_flag == BM_PLATFORM && __SYS_STATUS_BYTES_GET(virtual_billing) == SET)) && single_flow_sum > 0) { double price_double = 0; double single_use_money = 0; /*²ÎÊýÅäÖÃ*/ GasCumulant_Ladder_PeriodCfg(ladder_cfg_real_p, &ladder_price_cfg_para_new_g, &calendar_g); /*ËãÇ®*/ if (ladder_cfg_real_p->set_price_type_mode == SPM_NORMAL) // ÆÕͨ¼Æ·Ñ { if(start_flag == BM_DEVICE) billing_para_p->price_type_mode_now = BPM_NORMAL; billing_para_p->price_now = ladder_cfg_real_p->normal_price_now; price_double = ladder_cfg_real_p->normal_price_now * 0.0001f; single_use_money = single_flow_sum * price_double; billing_para_p->residual_gas_now = billing_para_p->balance_now / price_double; } else if (ladder_cfg_real_p->set_price_type_mode == SPM_LADDER) // °´ÆøÁ¿½×ÌÝ¼Æ·Ñ { single_use_money = GasCumulant_Ladder_PeriodCalculation(start_flag,single_flow_sum, ladder_cfg_real_p, billing_para_p); } else if (ladder_cfg_real_p->set_price_type_mode == SPM_TIME) // °´Ê±¼ä¶Î¼Æ·Ñ { } billing_para_p->use_money_sum += single_use_money; // µÃ³öÀÛ¼ÆÊ¹Óýð¶î billing_para_p->balance_now -= single_use_money; // µÃ³öÓà¶î /*¼Æ·Ñ/ÓÃÆøÏà¹Ø±¨¾¯ÅжÏ*/ State_Alarm_Bytes_BillingDataHandler(billing_para_p->balance_now, &billing_alarm_cfg_g); } State_Alarm_Bytes_NoGpra_NoGasHandler(&billing_alarm_cfg_g); if(billing_para_p->balance_now > (billing_alarm_cfg_g.balance_small_value[0] * 0.01f)) { /*½öÓà¶î²úÉúµÄÇ¿ÖÆÐÔ±¨¾¯¹Ø·§£¬µ±Óà¶î³ä×ãʱ×Ô¶¯½âËø*/ if(op_cl_valve_cause_id >= 0x90 && op_cl_valve_cause_id <= 0x94 && __SYS_STATUS_BYTES_GET(valve_state) == VALVE_CL) { if(__SYS_STATUS_BYTES_GET(valve_lock) == SET) { __VALVE_WORK_TYPE_SET(VWT_UNLOCK); // ½âËø£¨ÓÃÓÚ´æ´¢¼Ç¼£© __SYS_STATUS_BYTES_STATUS(valve_lock, RESET, AV_NORMAL); // ½âËø£¨ÓÃÓÚÕæÕý¿ØÖÆ£© } } } } /*ÆøÌåÀÛ»ýÁ¿-½×ÌݼÆËã*/ double GasCumulant_Ladder_PeriodCalculation(BILLING_MODE_T mode_flag,double single_flow_sum, LADDER_PRICE_CFG_PARA_T *ladder_cfg_p_p, BILLING_REAL_PARA_T *billing_para_p_p) { double price_double = 0; // µ¥¼Û double single_use_money = 0; // µ¥´ÎµÄʹÓýð¶î double ladder_cumulate_sc_before = billing_para_p_p->ladder_cumulate_sc; billing_para_p_p->ladder_cumulate_sc += single_flow_sum; // ½×ÌÝÖÜÆÚÄÚµÄÀÛ»ýÁ¿ if (billing_para_p_p->ladder_cumulate_sc <= ladder_cfg_p_p->set_ladder_cumulate[0]) // 0~100 { if(mode_flag == BM_DEVICE) billing_para_p_p->price_type_mode_now = BPM_LADDER_1; /*¼ÆËãµ¥´ÎµÄʹÓýð¶î*/ billing_para_p_p->price_now = ladder_cfg_p_p->set_ladder_price[0]; price_double = ladder_cfg_p_p->set_ladder_price[0] * 0.0001f; single_use_money = single_flow_sum * price_double; } else if (billing_para_p_p->ladder_cumulate_sc <= ladder_cfg_p_p->set_ladder_cumulate[1]) // 100~200 { price_double = ladder_cfg_p_p->set_ladder_price[1] * 0.0001f; if (ladder_cumulate_sc_before < ladder_cfg_p_p->set_ladder_cumulate[0]) // ÉÏ´ÎÊý¾ÝСÓÚÁÙ½çÖµ£¬±¾´ÎÊý¾ÝÈ´´óÓÚÁÙ½çÖµ { if(mode_flag == BM_DEVICE) billing_para_p_p->price_type_mode_now = BPM_LADDER_2; single_use_money = (ladder_cfg_p_p->set_ladder_cumulate[0] - ladder_cumulate_sc_before) * (ladder_cfg_p_p->set_ladder_price[0] * 0.0001f) + (billing_para_p_p->ladder_cumulate_sc - ladder_cfg_p_p->set_ladder_cumulate[0]) * price_double; billing_para_p_p->price_now = ladder_cfg_p_p->set_ladder_price[1]; } else single_use_money = single_flow_sum * price_double; } else if (billing_para_p_p->ladder_cumulate_sc <= ladder_cfg_p_p->set_ladder_cumulate[2]) // 200~300 { price_double = ladder_cfg_p_p->set_ladder_price[2] * 0.0001f; if (ladder_cumulate_sc_before < ladder_cfg_p_p->set_ladder_cumulate[1]) // ÉÏ´ÎÊý¾ÝСÓÚÁÙ½çÖµ£¬±¾´ÎÊý¾ÝÈ´´óÓÚÁÙ½çÖµ { if(mode_flag == BM_DEVICE) billing_para_p_p->price_type_mode_now = BPM_LADDER_3; single_use_money = (ladder_cfg_p_p->set_ladder_cumulate[1] - ladder_cumulate_sc_before) * (ladder_cfg_p_p->set_ladder_price[1] * 0.0001f) + (billing_para_p_p->ladder_cumulate_sc - ladder_cfg_p_p->set_ladder_cumulate[1]) * price_double; billing_para_p_p->price_now = ladder_cfg_p_p->set_ladder_price[2]; } else single_use_money = single_flow_sum * price_double; } else if (billing_para_p_p->ladder_cumulate_sc <= ladder_cfg_p_p->set_ladder_cumulate[3]) // 300~400 { price_double = ladder_cfg_p_p->set_ladder_price[3] * 0.0001f; if (ladder_cumulate_sc_before < ladder_cfg_p_p->set_ladder_cumulate[2]) // ÉÏ´ÎÊý¾ÝСÓÚÁÙ½çÖµ£¬±¾´ÎÊý¾ÝÈ´´óÓÚÁÙ½çÖµ { if(mode_flag == BM_DEVICE) billing_para_p_p->price_type_mode_now = BPM_LADDER_4; single_use_money = (ladder_cfg_p_p->set_ladder_cumulate[2] - ladder_cumulate_sc_before) * (ladder_cfg_p_p->set_ladder_price[2] * 0.0001f) + (billing_para_p_p->ladder_cumulate_sc - ladder_cfg_p_p->set_ladder_cumulate[2]) * price_double; billing_para_p_p->price_now = ladder_cfg_p_p->set_ladder_price[3]; } else single_use_money = single_flow_sum * price_double; } else // >400 { price_double = ladder_cfg_p_p->set_ladder_price[4] * 0.0001f; if (ladder_cumulate_sc_before < ladder_cfg_p_p->set_ladder_cumulate[3]) // ÉÏ´ÎÊý¾ÝСÓÚÁÙ½çÖµ£¬±¾´ÎÊý¾ÝÈ´´óÓÚÁÙ½çÖµ { if(mode_flag == BM_DEVICE) billing_para_p_p->price_type_mode_now = BPM_LADDER_5; single_use_money = (ladder_cfg_p_p->set_ladder_cumulate[3] - ladder_cumulate_sc_before) * (ladder_cfg_p_p->set_ladder_price[3] * 0.0001f) + (billing_para_p_p->ladder_cumulate_sc - ladder_cfg_p_p->set_ladder_cumulate[3]) * price_double; billing_para_p_p->price_now = ladder_cfg_p_p->set_ladder_price[4]; } else single_use_money = single_flow_sum * price_double; } return single_use_money; } /*ÆøÌåÀÛ»ýÁ¿-½×ÌÝÖÜÆÚÅäÖã¨ÖÜÆÚʱ¼äµ½½×ÌÝÀÛ»ýÁ¿ÇåÁ㣩*/ void GasCumulant_Ladder_PeriodCfg(LADDER_PRICE_CFG_PARA_T *ladder_cfg_old, LADDER_PRICE_CFG_PARA_T *ladder_cfg_new, __IO RTC_TimeDateTypeDef *calendar) { static uint8_t period_flag = 0; // ÖÜÆÚÊ״αê־λ static uint8_t next_period_start_time[6] = {0}; // ÏÂÒ»´ÎµÄÖÜÆÚ¿ªÊ¼Ê±¼ä uint8_t real_time[6] = {calendar->Year & 0xFF, calendar->Month, calendar->Date, calendar->Hour, calendar->Minute, calendar->Second}; // µ±Ç°Ê±¼ä /*ÐÂÀϰ汾²»Í¬ÇÒеļ۸ñ·½°¸ÉúЧʱ¼äµ½*/ if ((ladder_cfg_old->price_ver != ladder_cfg_new->price_ver) && Datecmp(ladder_cfg_new->price_scheme_start_time, real_time) <= 0) // м۸ñ·½°¸ÉúЧʱ¼ä <= µ±Ç°Ê±¼ä£¨Ð¼۸ñʱ¼äµ½£© { memcpy(ladder_cfg_old, ladder_cfg_new, sizeof(LADDER_PRICE_CFG_PARA_T)); // ¼Û¸ñ·½°¸Ìæ»» period_flag = 0; } if (ladder_cfg_old->set_price_type_mode == SPM_LADDER) // Èç¹ûµ±Ç°Êǽ×ÌÝ¼Æ·Ñ { if (period_flag == 0 && Datecmp(ladder_cfg_old->period_start_time, real_time) <= 0) // Ê״ε½´ïÖÜÆÚʱ¼ä { billing_real_para_g.ladder_cumulate_sc = 0; period_flag = 1; memcpy(next_period_start_time, ladder_cfg_old->period_start_time, sizeof(next_period_start_time)); StartTime_NextCalculation(ladder_cfg_old->period_unit, ladder_cfg_old->period_duration, next_period_start_time); } else if (period_flag) { if (Datecmp(next_period_start_time, real_time) <= 0) { if (ladder_cfg_old->period_state == PPS_CYCLICALLY) // Ñ­»·Ö´ÐÐ StartTime_NextCalculation(ladder_cfg_old->period_unit, ladder_cfg_old->period_duration, next_period_start_time); else if (ladder_cfg_old->period_state == PPS_ONLY_ONE) // Ö»Ö´ÐÐÒ»´Î ladder_cfg_old->set_price_type_mode = SPM_NORMAL; billing_real_para_g.ladder_cumulate_sc = 0; } } } } /*¼ÆËãÏ´οªÊ¼Ê±¼ä*/ void StartTime_NextCalculation(PRICE_PERIOD_UNIT_T price_unit, uint16_t time_duration, uint8_t *pNext_time) { uint8_t year_h, month_h, day_h, hour_h; uint8_t temp_quarter = 0; switch (price_unit) { case PPU_HOUR: hour_h = BCD_2_HEX_U8(pNext_time[3]) + time_duration; day_h = hour_h / 24; pNext_time[3] = HEX_2_BCD_U8(hour_h % 24); if (day_h) Add_days_CalculateYearMonTHDay(&pNext_time[0], &pNext_time[1], &pNext_time[2], day_h); break; case PPU_DAY: Add_days_CalculateYearMonTHDay(&pNext_time[0], &pNext_time[1], &pNext_time[2], time_duration); break; case PPU_MONTH: month_h = BCD_2_HEX_U8(pNext_time[1]) + time_duration; year_h = BCD_2_HEX_U8(pNext_time[0]); while (month_h > 12) { month_h -= 12; year_h++; } pNext_time[0] = HEX_2_BCD_U8(year_h); pNext_time[1] = HEX_2_BCD_U8(month_h); break; case PPU_QUARTER: year_h = BCD_2_HEX_U8(pNext_time[0]); month_h = BCD_2_HEX_U8(pNext_time[1]); temp_quarter = (month_h - 1) / 3; // 1~3Ϊ1 4~6Ϊ2 7~9Ϊ3 10~12Ϊ4 temp_quarter += time_duration; while (temp_quarter > 3) { temp_quarter -= 4; year_h++; } month_h = temp_quarter * 3 + 1; pNext_time[0] = HEX_2_BCD_U8(year_h); pNext_time[1] = HEX_2_BCD_U8(month_h); pNext_time[2] = 1; pNext_time[3] = 0; pNext_time[4] = 0; pNext_time[5] = 0; break; default: break; } } /****************************************** * func: Add_days_CalculateYearMonTHDay * desc: ¼ÆËãijÄêijÔÂijÌìÔö¼ÓЩÐíÌìÊýºó£¬ÎªÄ³ÄêijÔÂijÌì * input: pYear_bcd Äê·Ýbcd * pMonth_bcd Ô·Ýbcd * pDay_bcd Ììbcd * add_days Ôö¼ÓµÄÌìÊý * output: *pYear_bcd ¼ÆËãµÄ½á¹ûÄê·Ýbcd * *pMonth_bcd ¼ÆËãµÄ½á¹ûÔ·Ýbcd * *pDay_bcd ¼ÆËãµÄ½á¹ûÌìbcd * return: none * bug: ¸Ãº¯ÊýÌí¼ÓµÄÌìÊý²»ÄÜ¿äÁ½ÄêÒÔÉÏ£¬·ñÔò»á³ö´í¡£È磺¿ÉÒÔ´Ó2016ÄêÌí¼ÓÌìÊýµ½2017Ä꣬µ«Êǵ½2018ÄêÒÔÉÏ»á³ö´í *****************************************/ void Add_days_CalculateYearMonTHDay(uint8_t *pYear_bcd, uint8_t *pMonth_bcd, uint8_t *pDay_bcd, uint16_t add_days) { uint16_t year_h = BCD_2_HEX_U8(*pYear_bcd) + 2000, temp_year_h = 0, days_of_year = 0; uint8_t month_h = BCD_2_HEX_U8(*pMonth_bcd), day_h = BCD_2_HEX_U8(*pDay_bcd), i; uint8_t leap = ((year_h % 4 == 0) && (year_h % 100 != 0)) || (year_h % 400 == 0); // 1ΪÈòÄê 0ΪƽÄê uint8_t days_of_month[2][13] = {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; /*¼ÆËã¸ÃÄê¸ÃÔ¸ÃÌìΪµÚ¼¸Ìì*/ for (i = 1; i < month_h; i++) days_of_year += days_of_month[leap][i]; days_of_year += day_h; /*Ôö¼ÓÌìÊý*/ days_of_year += add_days; temp_year_h = year_h; if (leap) { if (days_of_year > 366) { temp_year_h += days_of_year / 366; days_of_year -= 366; } } else { if (days_of_year > 365) { temp_year_h += days_of_year / 365; days_of_year -= 365; } } leap = ((temp_year_h % 4 == 0) && (temp_year_h % 100 != 0)) || (temp_year_h % 400 == 0); for (i = 1; days_of_year > days_of_month[leap][i]; i++) days_of_year -= days_of_month[leap][i]; *pYear_bcd = HEX_2_BCD_U8(temp_year_h - 2000); *pMonth_bcd = HEX_2_BCD_U8(i); *pDay_bcd = HEX_2_BCD_U8(days_of_year); }