Work_XCT.c 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-08-16 RuoFeng the first version
  9. */
  10. /*********************↓ define ↓************************/
  11. #define DBG_ENABLE
  12. #define DBG_COLOR
  13. #define DBG_TAG "xct"
  14. #define DBG_LEVEL DBG_INFO
  15. #include <rtdbg.h>
  16. #define LOG_INR 10 // 默认的log打印间隔(作用域在本文件)
  17. #define TakeINR 10 // mins 默认的拍照间隔
  18. #define RTU_OFF_MAX 180
  19. #define WAIT_NET_MAX 180
  20. #define ENABLE_WORK (Check_Allow_Work() == res_ok)
  21. #define NEW_TIMESTAMP tm_to_timestamp()
  22. /*********************↑ define ↑************************/
  23. /**
  24. *
  25. *
  26. *
  27. *
  28. * */
  29. /*********************↓ include ↓************************/
  30. #include "Work_XCT.h"
  31. #include "rs485.h"
  32. #include "control.h"
  33. #include "test.h"
  34. #include <easyflash.h>
  35. #include "dtu_uart2.h"
  36. /*********************↑ include ↑************************/
  37. /**
  38. *
  39. *
  40. *
  41. *
  42. * */
  43. /*********************↓ extern ↓************************/
  44. extern Temporal_list Check_Work_time_period(uint8_t coll_ch);
  45. extern works_def ws_now;
  46. extern Device_Status_typedef device_status;
  47. extern void HMI_WRITE(char *fmt, ...);
  48. extern JD_Test_Sta jts;
  49. extern Res_def Mtor_Control_ZP(Motor_Ctl_type mct);
  50. extern Sensor sensor[MAX_SENSOR_NUM];
  51. extern Temporal_list Check_Work_time_period_0oclock(void);
  52. extern RTC_DateTypeDef GetDate;
  53. extern RTC_TimeTypeDef GetTime;
  54. extern uint8_t ReFlash_RTC(void);
  55. extern RTC_DateTypeDef GetDate;
  56. extern RTC_TimeTypeDef GetTime;
  57. extern uint32_t tm_to_timestamp(void);
  58. /*********************↑ extern ↑************************/
  59. /**
  60. *
  61. *
  62. *
  63. *
  64. * */
  65. /********************↓ declaration ↓***********************/
  66. static char rturead(void);
  67. /********************↑ declaration ↑***********************/
  68. /**
  69. *
  70. *
  71. *
  72. *
  73. * */
  74. /*********************↓ global variables ↓************************/
  75. static uint16_t takephoto_cnt = 0; // 拍照触发计数
  76. static uint16_t wait_data_cnt = 0; // 上报数据计数
  77. static uint32_t tm_data = 0; // 计算数据时间
  78. static uint32_t tm_photo = 0; // 计算图片时间
  79. volatile SYSCFG syscfg = {0}; // 系统配置
  80. volatile Limit limit = {0}; // 各种控的开关和参数
  81. volatile Luxwork lwork = {0}; // 光控相关参数
  82. volatile Sunwork swork = {0}; // 晨曦相关参数
  83. volatile wm_Def workmode = TypeMAX_wx; // 工作模式
  84. WorkMode_Def WorkModeList[TypeMAX_wx] = // 工作模式类型
  85. {
  86. {RunTime_wx, "时控模式"},
  87. {RunLight_wx, "光控模式"},
  88. {RunFRMS_wx, "晨曦模式"}};
  89. static uint16_t INR_PIC = 0; // 图片上传间隔
  90. static uint16_t INR_DAT = 0; // 图片上传间隔
  91. /*********************↑ global variables ↑************************/
  92. /**
  93. *
  94. *
  95. *
  96. *
  97. * */
  98. /**
  99. * @brief 执行一次清灰
  100. *
  101. * mode 0 = 日常, mode = 1 测试
  102. *
  103. */
  104. static void FB_Clean(char mode)
  105. {
  106. char recode_day = 0;
  107. ef_get_env_blob("FB_Clean", &recode_day, sizeof(recode_day), NULL);
  108. if(mode == 0)
  109. {
  110. if (recode_day != GetDate.Date && GetTime.Hours == 12 && GetTime.Minutes < 10)
  111. {
  112. rt_kprintf("ready to FB_Clean\n");
  113. }
  114. else
  115. {
  116. return;
  117. }
  118. }
  119. else if(mode != 1)
  120. {
  121. return;
  122. }
  123. else
  124. {
  125. rt_kprintf("FB_Clean 手动测试\n");
  126. }
  127. Recode_e_code(e_FB_Clean, GetDate.Date, "清灰开始操作");
  128. ctr_led(ON);
  129. LOG_I("STEP1 > ctr_led(ON)\n");
  130. ctr_Collect_Fan(ON, 100);
  131. LOG_I("STEP2 > ctr_Collect_Fan(ON)\n");
  132. rt_thread_mdelay(2000);
  133. LOG_I("STEP3 > Mtor_Control_CM > mct_Foreward\n");
  134. uint16_t Motor_L , Motor_R;
  135. Motor_L = TURN_CM_L;
  136. Motor_R = TURN_CM_R;
  137. rt_pin_mode(Motor_L, PIN_MODE_OUTPUT);
  138. rt_pin_mode(Motor_R, PIN_MODE_OUTPUT);
  139. rt_pin_write(Motor_R, OFF);
  140. rt_pin_write(Motor_L, ON);
  141. LOG_I("STEP4 > Mtor_Control_ZP > mct_Foreward\n");
  142. Mtor_Control_ZP(mct_Foreward);
  143. rt_thread_mdelay(2000);
  144. Mtor_Control_ZP(mct_Foreward);
  145. rt_thread_mdelay(2000);
  146. Mtor_Control_ZP(mct_Foreward);
  147. rt_thread_mdelay(2000);
  148. Mtor_Control_ZP(mct_Reversal);
  149. rt_thread_mdelay(2000);
  150. Mtor_Control_ZP(mct_Reversal);
  151. rt_thread_mdelay(2000);
  152. Mtor_Control_ZP(mct_Reversal);
  153. LOG_I("STEP5 > FB_Clean finsh \n");
  154. ctr_led(OFF);
  155. ctr_Collect_Fan(OFF, 0);
  156. rt_pin_write(Motor_R, OFF);
  157. rt_pin_write(Motor_L, OFF);
  158. ef_set_env_blob("FB_Clean", &recode_day, sizeof(recode_day));
  159. }
  160. static void FBClean_Test(void)
  161. {
  162. FB_Clean(1);
  163. }
  164. MSH_CMD_EXPORT(FBClean_Test , FBClean_Test);
  165. /**
  166. * @brief 记录当前时刻
  167. *
  168. * @param time 时间戳
  169. */
  170. static void recode_timestampe_NEW(uint32_t *tim)
  171. {
  172. ReFlash_RTC();
  173. *tim = NEW_TIMESTAMP;
  174. if (tim == &tm_photo)
  175. {
  176. rt_kprintf("recode_timestampe (photo) > %d sec\n", *tim);
  177. }
  178. else
  179. {
  180. rt_kprintf("recode_timestampe (data ) > %d sec\n", *tim);
  181. }
  182. rt_thread_mdelay(1000);
  183. }
  184. /**
  185. * @brief 计算差值
  186. *
  187. * @param time 时间戳
  188. * @return uint32_t 差值
  189. */
  190. static uint32_t math_timestampe_NEW(uint32_t *tim)
  191. {
  192. // uint16_t log_en_inr = LOG_INR * 3; // 打印log的速度 数值越小 打印越频繁
  193. // static int16_t log_en_cnt = -1;
  194. if (*tim == NEW_TIMESTAMP)
  195. {
  196. rt_thread_mdelay(1000);
  197. }
  198. ReFlash_RTC();
  199. uint32_t now = NEW_TIMESTAMP;
  200. uint32_t val = (now - *tim);
  201. if (val > 0 && val < ((device_status.dattim + device_status.photim) * 60))
  202. {
  203. return val;
  204. }
  205. else
  206. {
  207. if (tim == &tm_photo)
  208. {
  209. rt_kprintf("math_timestampe fail (photo) > %d (now : %d >>> tim : %d) \n", val, now, *tim);
  210. recode_timestampe_NEW(tim);
  211. }
  212. else
  213. {
  214. rt_kprintf("math_timestampe fail (data ) > %d (now : %d >>> tim : %d) \n", val, now, *tim);
  215. recode_timestampe_NEW(tim);
  216. }
  217. }
  218. return 0;
  219. }
  220. /**
  221. * @brief 250826 新增整点匹配逻辑
  222. *
  223. * @return uint8_t
  224. */
  225. // 计算下一次整点上报时间并返回进度
  226. // int get_report_progress(int interval_minutes, int read_type, int time_offset)
  227. // {
  228. // static uint32_t last_judge_minute = 0xFFFFFFFF; // 上次判断模式触发的时间(总分钟数)
  229. // static uint32_t current_cycle_base = 0xFFFFFFFF; // 当前周期的基准整点时间
  230. // int current_minute_total;
  231. // int progress = 0;
  232. // // 刷新RTC时间
  233. // ReFlash_RTC();
  234. // // 计算当前时间从0点开始的总分钟数
  235. // current_minute_total = GetTime.Hours * 60 + GetTime.Minutes;
  236. // // 如果是第一次调用,初始化
  237. // if (current_cycle_base == 0xFFFFFFFF)
  238. // {
  239. // current_cycle_base = (current_minute_total / interval_minutes) * interval_minutes;
  240. // last_judge_minute = 0xFFFFFFFF;
  241. // }
  242. // // 计算考虑偏移量的期望上报时间
  243. // int expected_minute = current_cycle_base + interval_minutes + time_offset;
  244. // if (expected_minute < 0)
  245. // expected_minute += 1440;
  246. // if (expected_minute >= 1440)
  247. // expected_minute -= 1440;
  248. // // 计算考虑偏移量的周期开始时间
  249. // int cycle_start_minute = current_cycle_base + time_offset;
  250. // if (cycle_start_minute < 0)
  251. // cycle_start_minute += 1440;
  252. // if (cycle_start_minute >= 1440)
  253. // cycle_start_minute -= 1440;
  254. // if (read_type == READ_TYPE_QUERY)
  255. // {
  256. // // 查询模式:简单计算进度,不管理状态
  257. // int elapsed_minutes;
  258. // if (current_minute_total >= cycle_start_minute)
  259. // {
  260. // elapsed_minutes = current_minute_total - cycle_start_minute;
  261. // }
  262. // else
  263. // {
  264. // elapsed_minutes = (1440 - cycle_start_minute) + current_minute_total;
  265. // }
  266. // progress = (elapsed_minutes * 100) / interval_minutes;
  267. // // 限制进度范围,防止溢出
  268. // if (progress < 0)
  269. // progress = 0;
  270. // if (progress > 1000)
  271. // progress = 1000; // 最大1000%防止异常
  272. // }
  273. // else
  274. // { // READ_TYPE_JUDGE
  275. // // 判断模式:管理状态并确保单次触发
  276. // // 检查是否应该触发
  277. // int should_trigger = 0;
  278. // if (current_minute_total >= expected_minute)
  279. // {
  280. // should_trigger = 1;
  281. // }
  282. // else if (expected_minute - current_minute_total > 1200)
  283. // { // 跨天
  284. // should_trigger = 1;
  285. // }
  286. // if (should_trigger)
  287. // {
  288. // // 检查是否已经在本周期触发过
  289. // if (last_judge_minute != current_cycle_base)
  290. // {
  291. // // 首次触发本周期
  292. // progress = 100;
  293. // last_judge_minute = current_cycle_base;
  294. // // 更新到下一个周期
  295. // current_cycle_base += interval_minutes;
  296. // if (current_cycle_base >= 1440)
  297. // {
  298. // current_cycle_base -= 1440;
  299. // }
  300. // }
  301. // else
  302. // {
  303. // // 已经触发过,计算超时进度(限制范围)
  304. // int overtime_minutes;
  305. // if (current_minute_total >= expected_minute)
  306. // {
  307. // overtime_minutes = current_minute_total - expected_minute;
  308. // }
  309. // else
  310. // {
  311. // overtime_minutes = (1440 - expected_minute) + current_minute_total;
  312. // }
  313. // progress = 100 + (overtime_minutes * 100 / interval_minutes);
  314. // // 严格限制进度范围,防止11340%这样的异常
  315. // if (progress > 1000)
  316. // {
  317. // progress = 1000;
  318. // last_judge_minute = 0xFFFFFFFF; // 重置触发状态
  319. // }
  320. // // 如果超时太久,强制进入下一个周期
  321. // if (overtime_minutes >= interval_minutes)
  322. // {
  323. // current_cycle_base = (current_minute_total / interval_minutes) * interval_minutes;
  324. // last_judge_minute = 0xFFFFFFFF; // 重置触发状态
  325. // }
  326. // }
  327. // }
  328. // else
  329. // {
  330. // // 还在周期内,计算正常进度
  331. // int elapsed_minutes;
  332. // if (current_minute_total >= cycle_start_minute)
  333. // {
  334. // elapsed_minutes = current_minute_total - cycle_start_minute;
  335. // }
  336. // else
  337. // {
  338. // elapsed_minutes = (1440 - cycle_start_minute) + current_minute_total;
  339. // }
  340. // progress = (elapsed_minutes * 100) / interval_minutes;
  341. // // 重置触发状态(新周期开始)
  342. // if (last_judge_minute != current_cycle_base || progress > 300)
  343. // {
  344. // last_judge_minute = 0xFFFFFFFF;
  345. // }
  346. // }
  347. // }
  348. // return progress;
  349. // }
  350. /**
  351. * @brief 250826 新增整点匹配逻辑
  352. *
  353. * @return uint8_t
  354. */
  355. uint8_t GetCollInfo(void)
  356. {
  357. // uint16_t inr = 0;
  358. // (syscfg.photim >= 5) ? (inr = syscfg.photim - 1) : (inr = TakeINR);
  359. return (math_timestampe_NEW(&tm_photo) * 100) / (INR_PIC);
  360. }
  361. /**
  362. * @brief
  363. *
  364. * @return int8_t -1(超时) >1(进度百分比)
  365. */
  366. int8_t Get_luxworkTime(void)
  367. {
  368. uint16_t log_en_inr = LOG_INR * 3; // 打印log的速度 数值越小 打印越频繁
  369. static int16_t log_en_cnt = -1;
  370. ReFlash_RTC();
  371. uint32_t start = 0, now = 0;
  372. start = lwork.start_time.Hours * 60 + lwork.start_time.Minutes;
  373. now = GetTime.Hours * 60 + GetTime.Minutes;
  374. if (abs(GetTime.Hours - lwork.start_time.Hours) >= 10 && GetTime.Hours < lwork.start_time.Hours)
  375. {
  376. now += 1440;
  377. }
  378. if ((now - start) > (limit.LuxTime * 60))
  379. {
  380. return -2;
  381. }
  382. else
  383. {
  384. if (chk_log_time)
  385. LOG_I("luxtime %d%% \n", ((now - start) * 100) / (limit.LuxTime * 60));
  386. return ((now - start) * 100) / (limit.LuxTime * 60);
  387. }
  388. return -1;
  389. }
  390. /**
  391. * @brief 获取晨曦模式工作进度 不在工作范围 返回负数
  392. *
  393. * @return int8_t val(-1 未开始工作 -2 参数校验失败)
  394. */
  395. int8_t Get_swork_percent(void)
  396. {
  397. uint32_t start = 0, end = 0, temp1 = 0, now = 0;
  398. if (swork.sunup_time.Hours == 0 || swork.sundown_time.Hours == 0)
  399. {
  400. swork.sunup_time.Hours = 7;
  401. swork.sunup_time.Minutes = 30;
  402. swork.sundown_time.Hours = 17;
  403. swork.sundown_time.Minutes = 20;
  404. ef_set_env_blob((const char *)"swork", (void *)&swork, sizeof(swork));
  405. }
  406. if (swork.start_time.Hours == 0 || swork.end_time.Hours == 0)
  407. {
  408. // 计算工作开始时间
  409. swork.start_time.Hours = (swork.sundown_time.Hours * 60 + swork.sundown_time.Minutes - swork.lseek) / 60;
  410. swork.start_time.Minutes = (swork.sundown_time.Hours * 60 + swork.sundown_time.Minutes - swork.lseek) % 60;
  411. swork.start_time.Seconds = swork.sundown_time.Seconds;
  412. // 计算工作结束时间
  413. swork.end_time.Hours = (swork.sunup_time.Hours * 60 + swork.sunup_time.Minutes + swork.lseek) / 60;
  414. swork.end_time.Minutes = (swork.sunup_time.Hours * 60 + swork.sunup_time.Minutes + swork.lseek) % 60;
  415. swork.end_time.Seconds = swork.sunup_time.Seconds;
  416. }
  417. if ((swork.start_time.Hours + swork.end_time.Hours) == 0 || swork.start_time.Hours < swork.end_time.Hours)
  418. {
  419. return -2;
  420. }
  421. now = GetTime.Hours * 3600 + GetTime.Minutes * 60 + GetTime.Seconds;
  422. start = swork.start_time.Hours * 3600 + swork.start_time.Minutes * 60 + swork.start_time.Seconds;
  423. end = swork.end_time.Hours * 3600 + swork.end_time.Minutes * 60 + swork.end_time.Seconds;
  424. if (now < start && now > end)
  425. {
  426. return -1;
  427. }
  428. if (GetTime.Hours > swork.end_time.Hours)
  429. {
  430. end += (24 * 3600);
  431. }
  432. temp1 = end - start;
  433. // rt_kprintf("now %d ALL %d\n" , (now - start) , temp1);
  434. if (((now - start) > temp1) || ((now - start) * 100 / temp1) > 100)
  435. {
  436. return -3;
  437. }
  438. return (now - start) * 100 / temp1;
  439. }
  440. int8_t Get_percent(void)
  441. {
  442. ReFlash_RTC();
  443. uint32_t now = GetTime.Hours * 3600 + GetTime.Minutes * 60 + GetTime.Seconds;
  444. uint32_t sh1 = device_status.collecting_sh1 * 3600;
  445. uint32_t eh1 = device_status.collecting_eh1 * 3600;
  446. // 情况1:不跨午夜
  447. if (sh1 <= eh1)
  448. {
  449. if (now < sh1 || now >= eh1)
  450. return -1;
  451. return (now - sh1) * 100 / (eh1 - sh1);
  452. }
  453. // 情况2:跨午夜
  454. else
  455. {
  456. // 当前时间在晚上时段(sh1~24:00)
  457. if (now >= sh1)
  458. {
  459. uint32_t segment_end = 24 * 3600;
  460. uint32_t segment_len = segment_end - sh1;
  461. return (now - sh1) * 100 / segment_len;
  462. }
  463. // 当前时间在早上时段(00:00~eh1)
  464. else if (now < eh1)
  465. {
  466. uint32_t total_len = (24 * 3600 - sh1) + eh1;
  467. uint32_t elapsed = (24 * 3600 - sh1) + now;
  468. return elapsed * 100 / total_len;
  469. }
  470. // 不在工作时段
  471. else
  472. {
  473. return -1;
  474. }
  475. }
  476. }
  477. /**
  478. * @brief 记录日出日落的时间
  479. *
  480. */
  481. void Get_SunTime(void)
  482. {
  483. #define rec_MAX 6
  484. static uint8_t pointer = 0, start_get = 0;
  485. static uint16_t recode_lux[rec_MAX] = {0}; // 记录历史光照值
  486. uint16_t avg = 0, has0 = 0;
  487. if (!sensor[s_Lux].online || (strstr(sensor[s_Lux].eValue, "-99.99") != NULL))
  488. {
  489. return;
  490. }
  491. // 赋值
  492. recode_lux[pointer] = sensor[s_Lux].value;
  493. // rt_kprintf("set %d in pos > %d\n" ,recode_lux[pointer] ,pointer);
  494. // 偏移指针
  495. if (++pointer >= rec_MAX)
  496. {
  497. pointer = 0;
  498. start_get = 1;
  499. }
  500. for (uint8_t a = 0; a < rec_MAX; a++)
  501. {
  502. (a == 0) ? rt_kprintf("recode_lux > %d ", recode_lux[a]) : rt_kprintf(" > %d ", recode_lux[a]);
  503. avg += recode_lux[a];
  504. if ((a + 1) == rec_MAX)
  505. {
  506. avg /= rec_MAX;
  507. rt_kprintf(" avg %d\n", avg);
  508. }
  509. if (recode_lux[a] == 0)
  510. {
  511. has0 = 1;
  512. }
  513. }
  514. if (start_get != 1)
  515. {
  516. return;
  517. }
  518. // if(GetTime.Hours >= 13 && GetTime.Hours < 15 && GetDate.Year > 20) //限定判断区间 (16-20 点之间 日落)
  519. if (GetTime.Hours >= 16 && GetTime.Hours < 21 && GetDate.Year > 20) // 限定判断区间 (16-20 点之间 日落)
  520. {
  521. if (has0 == 0 && (avg * 100) >= (swork.slux_set * 9) && (avg * 100) <= (swork.slux_set * 11))
  522. {
  523. start_get = 0;
  524. pointer = 0;
  525. memset(recode_lux, 0, sizeof(recode_lux));
  526. // 记录日落时间
  527. swork.sundown_time.Hours = GetTime.Hours;
  528. swork.sundown_time.Minutes = GetTime.Minutes;
  529. swork.sundown_time.Seconds = GetTime.Seconds;
  530. // 计算工作开始时间
  531. swork.start_time.Hours = (swork.sundown_time.Hours * 60 + swork.sundown_time.Minutes - swork.lseek) / 60;
  532. swork.start_time.Minutes = (swork.sundown_time.Hours * 60 + swork.sundown_time.Minutes - swork.lseek) % 60;
  533. swork.start_time.Seconds = swork.sundown_time.Seconds;
  534. rt_kprintf("get sundown_time %02d:%02d:%02d \n", swork.sundown_time.Hours, swork.sundown_time.Minutes, swork.sundown_time.Seconds);
  535. rt_kprintf("get start_time %02d:%02d:%02d \n\n", swork.start_time.Hours, swork.start_time.Minutes, swork.start_time.Seconds);
  536. ef_set_env_blob("swork", (const void *)&swork, sizeof(swork));
  537. }
  538. else
  539. {
  540. rt_kprintf("avg %d not in range %d-%d\n", (avg * 100), (swork.slux_set * 9), (swork.slux_set * 11));
  541. }
  542. }
  543. // if(GetTime.Hours >= 13 && GetTime.Hours < 16 && GetDate.Year > 20) //限定判断区间 (4-9 点之间 日出)
  544. if (GetTime.Hours >= 4 && GetTime.Hours < 9 && GetDate.Year > 20) // 限定判断区间 (4-9 点之间 日出)
  545. {
  546. if (has0 == 0 && (avg * 100) >= (swork.slux_set * 9) && (avg * 100) <= (swork.slux_set * 11))
  547. {
  548. start_get = 0;
  549. pointer = 0;
  550. memset(recode_lux, 0, sizeof(recode_lux));
  551. // 记录日出时间
  552. swork.sunup_time.Hours = GetTime.Hours;
  553. swork.sunup_time.Minutes = GetTime.Minutes;
  554. swork.sunup_time.Seconds = GetTime.Seconds;
  555. // 计算工作结束时间
  556. swork.end_time.Hours = (swork.sunup_time.Hours * 60 + swork.sunup_time.Minutes + swork.lseek) / 60;
  557. swork.end_time.Minutes = (swork.sunup_time.Hours * 60 + swork.sunup_time.Minutes + swork.lseek) % 60;
  558. swork.end_time.Seconds = swork.sunup_time.Seconds;
  559. rt_kprintf("get sunup time %02d:%02d:%02d \n", swork.sunup_time.Hours, swork.sunup_time.Minutes, swork.sunup_time.Seconds);
  560. rt_kprintf("get end_time %02d:%02d:%02d \n\n", swork.end_time.Hours, swork.end_time.Minutes, swork.end_time.Seconds);
  561. ef_set_env_blob("swork", (const void *)&swork, sizeof(swork));
  562. }
  563. else
  564. {
  565. rt_kprintf("avg %d not in range %d-%d\n", (avg * 100), (swork.slux_set * 9), (swork.slux_set * 11));
  566. }
  567. }
  568. }
  569. /**
  570. * @brief 确认当前工作模式
  571. *
  572. */
  573. void Get_work_mode(void)
  574. {
  575. /**
  576. * @brief 开始确认
  577. *
  578. */
  579. static uint8_t ENPrint = 1;
  580. wm_Def bak = workmode;
  581. if (swork.EN == ON)
  582. {
  583. workmode = RunFRMS_wx;
  584. if (ENPrint || bak != workmode)
  585. {
  586. rt_kprintf(" 晨曦工作模式 \n\n");
  587. rt_kprintf(" 日落 - 日出 %02d:%02d:%02d ~ %02d:%02d:%02d\n",
  588. swork.sundown_time.Hours,
  589. swork.sundown_time.Minutes,
  590. swork.sundown_time.Seconds,
  591. swork.sunup_time.Hours,
  592. swork.sunup_time.Minutes,
  593. swork.sunup_time.Seconds);
  594. rt_kprintf(" 开始 - 结束 %02d:%02d:%02d ~ %02d:%02d:%02d\n",
  595. swork.start_time.Hours,
  596. swork.start_time.Minutes,
  597. swork.start_time.Seconds,
  598. swork.end_time.Hours,
  599. swork.end_time.Minutes,
  600. swork.end_time.Seconds);
  601. rt_kprintf(" 偏移时间 > %d 光控阈值 > %d\n\n", swork.lseek, swork.slux_set);
  602. bak = workmode;
  603. ENPrint = 0;
  604. }
  605. return;
  606. }
  607. if (limit.LuxEN == ON)
  608. {
  609. workmode = RunLight_wx;
  610. if (ENPrint || bak != workmode)
  611. {
  612. rt_kprintf("\n 光控模式 %d 小时\n\n", limit.LuxTime);
  613. bak = workmode;
  614. ENPrint = 0;
  615. }
  616. return;
  617. }
  618. workmode = RunTime_wx;
  619. if (ENPrint || bak != workmode)
  620. {
  621. rt_kprintf("\n 时控模式 %d-%d 时\n\n", device_status.collecting_sh1, device_status.collecting_eh1);
  622. bak = workmode;
  623. ENPrint = 0;
  624. }
  625. }
  626. #define Temp_Tig_MX 20
  627. /**
  628. * @brief 检查是否允许工作
  629. *
  630. * @return Caw_def 校验值
  631. */
  632. Caw_def Check_Allow_Work(void)
  633. {
  634. uint16_t log_en_inr = LOG_INR; // 打印log的速度 数值越小 打印越频繁
  635. static int16_t log_en_cnt = -1;
  636. static uint8_t lux_getin_cnt = 0;
  637. static uint8_t lux_getout_cnt = 0;
  638. rt_thread_mdelay(15);
  639. Get_work_mode();
  640. switch (workmode)
  641. {
  642. /**
  643. * @brief 光控模式
  644. *
  645. */
  646. case RunLight_wx:
  647. // rt_kprintf("sensor[s_Lux].value %d Luxlimit %d online %d on %d\n" , sensor[s_Lux].value , Luxlimit , sensor[s_Lux].online , limit.LuxEN);
  648. // lwork默认
  649. if (lwork.Read == 0)
  650. {
  651. ef_get_env_blob("lwork", (void *)&lwork, sizeof(lwork), NULL);
  652. if (lwork.Read == 0)
  653. {
  654. lwork.Read = 1;
  655. lwork.start_work = OFF;
  656. lwork.lux_set = Luxlimit_def;
  657. ef_set_env_blob("lwork", (void *)&lwork, sizeof(lwork));
  658. }
  659. }
  660. if (lwork.lux_set == 0)
  661. {
  662. lwork.lux_set = Luxlimit_def;
  663. ef_set_env_blob("lwork", (void *)&lwork, sizeof(lwork));
  664. }
  665. // lwork默认
  666. if (sensor[s_Lux].online >= 1 && (sensor[s_Lux].value * 10) > lwork.lux_set) // 退出
  667. {
  668. lux_getout_cnt++;
  669. if (chk_log_time)
  670. {
  671. LOG_I("CAW:光控\n");
  672. }
  673. if (lux_getout_cnt >= 3)
  674. {
  675. lux_getout_cnt = 0;
  676. device_status.lps_sta = 1;
  677. if (lwork.start_work == ON)
  678. {
  679. Recode_e_code(e_exit_luxwork, (sensor[s_Lux].value * 10), "光控模式退出(光照良好)");
  680. lwork.start_work = OFF;
  681. ef_set_env_blob("lwork", (void *)&lwork, sizeof(lwork));
  682. }
  683. }
  684. return res_Light;
  685. }
  686. if (sensor[s_Lux].online >= 1 && (sensor[s_Lux].value * 10) <= lwork.lux_set) // 进入
  687. {
  688. if (workmode != RunLight_wx)
  689. {
  690. lux_getin_cnt++;
  691. if (lux_getin_cnt >= 3)
  692. {
  693. lux_getin_cnt = 0;
  694. lwork.Read = 1;
  695. lwork.start_work = ON;
  696. ReFlash_RTC();
  697. lwork.start_time.Hours = GetTime.Hours;
  698. lwork.start_time.Minutes = GetTime.Minutes;
  699. LOG_W("进入光控工作模式 %d", ef_set_env_blob("lwork", (void *)&lwork, sizeof(lwork)));
  700. Recode_e_code(e_getin_luxwork, 0, "进入光控工作模式");
  701. }
  702. }
  703. }
  704. if (Get_luxworkTime() < 0)
  705. {
  706. device_status.lps_sta = 1;
  707. if (lwork.start_work == ON)
  708. {
  709. Recode_e_code(e_getout_luxwork, 0, "光控工作模式结束");
  710. lwork.start_work = OFF;
  711. ef_set_env_blob("lwork", (void *)&lwork, sizeof(lwork));
  712. }
  713. return res_luxout;
  714. }
  715. device_status.lps_sta = 0;
  716. break;
  717. /**
  718. * @brief 时控模式
  719. *
  720. */
  721. case RunTime_wx:
  722. if ((device_status.collecting_sh1 == device_status.collecting_eh1) ||
  723. (device_status.collecting_sh1 == 0 && device_status.collecting_eh1 == 24)) // 全天候牛马
  724. {
  725. if (chk_log_time)
  726. {
  727. LOG_I("CAW:全天候牛马\n");
  728. }
  729. }
  730. else if (device_status.collecting_eh1 < device_status.collecting_sh1) // 跨0点牛马
  731. {
  732. if (Check_Work_time_period_0oclock() != tl_Center)
  733. {
  734. if (chk_log_time)
  735. {
  736. LOG_I("CAW:未在工作时间 0点\n");
  737. }
  738. return res_Time;
  739. }
  740. }
  741. else // 正常牛马
  742. {
  743. if (Check_Work_time_period(1) != tl_Center)
  744. {
  745. if (chk_log_time)
  746. {
  747. LOG_I("CAW:未在工作时间\n");
  748. }
  749. return res_Time;
  750. }
  751. }
  752. break;
  753. /**
  754. * @brief 晨曦模式
  755. *
  756. */
  757. case RunFRMS_wx:
  758. if ((swork.sundown_time.Minutes + swork.sunup_time.Minutes) == 0)
  759. {
  760. return res_Sunout;
  761. }
  762. // rt_kprintf("RunFRMS_wx %d\n" , Get_swork_percent());
  763. if (Get_swork_percent() < 0)
  764. {
  765. return res_Sunout;
  766. }
  767. break;
  768. default:
  769. break;
  770. }
  771. static uint8_t temp_up_cnt = 0;
  772. static uint8_t temp_dn_cnt = 0;
  773. /**
  774. * @brief 温湿度
  775. *
  776. */
  777. // rt_kprintf("sensor[s_Temp].value %d Luxlimit %d\n" , sensor[s_Temp].value , limit.temp_up);
  778. if (sensor[s_Temp].online >= 1 && (sensor[s_Temp].value) > (limit.temp_up * 10) && limit.temhumEN == ON)
  779. {
  780. if (temp_up_cnt >= Temp_Tig_MX)
  781. {
  782. LOG_I("CAW:触发温控上限 %d\n", temp_up_cnt);
  783. return res_Temp;
  784. }
  785. temp_up_cnt++;
  786. rt_thread_mdelay(1000);
  787. // if (chk_log_time || 1)
  788. // {
  789. // LOG_I("CAW:温控上限 …%d\n", temp_up_cnt);
  790. // }
  791. if (temp_up_cnt >= Temp_Tig_MX)
  792. {
  793. if (device_status.temp_status == 0)
  794. {
  795. LOG_I("CAW:触发温控上限 %d\n", temp_up_cnt);
  796. }
  797. device_status.temp_status = 1;
  798. return res_Temp;
  799. }
  800. }
  801. else if (temp_up_cnt > 0)
  802. {
  803. LOG_I("CAW:解除温控上限进行中 %d\n", temp_up_cnt);
  804. temp_up_cnt--;
  805. rt_thread_mdelay(1000);
  806. if (temp_up_cnt == 0)
  807. {
  808. if (device_status.temp_status > 0)
  809. LOG_I("CAW:解除温控上限\n");
  810. device_status.temp_status = 0;
  811. }
  812. }
  813. if (sensor[s_Temp].online >= 1 && (sensor[s_Temp].value) < (limit.temp_dw * 10) && limit.temhumEN == ON)
  814. {
  815. if (temp_dn_cnt >= Temp_Tig_MX)
  816. {
  817. return res_Temp;
  818. }
  819. // rt_kprintf("(sensor[s_Temp].value) %d (limit.temp_dw * 10) %d \n" , (sensor[s_Temp].value) , (limit.temp_dw * 10));
  820. temp_dn_cnt++;
  821. rt_thread_mdelay(1000);
  822. // if (chk_log_time || 1)
  823. // {
  824. // LOG_I("CAW:温控下限 …%d\n", temp_dn_cnt);
  825. // }
  826. if (temp_dn_cnt >= Temp_Tig_MX)
  827. {
  828. temp_dn_cnt = 0;
  829. if (device_status.temp_status == 0)
  830. {
  831. LOG_I("CAW:触发温控下限 %d\n", temp_dn_cnt);
  832. }
  833. device_status.temp_status = 2;
  834. return res_Temp;
  835. }
  836. }
  837. else if (temp_dn_cnt > 0)
  838. {
  839. temp_dn_cnt--;
  840. rt_thread_mdelay(1000);
  841. if (temp_dn_cnt == 0)
  842. {
  843. if (device_status.temp_status > 0)
  844. LOG_I("CAW:解除温控下限\n");
  845. device_status.temp_status = 0;
  846. }
  847. }
  848. /**
  849. * @brief 温湿度
  850. *
  851. */
  852. /**
  853. * @brief 雨控
  854. *
  855. */
  856. // if (sensor[s_Rain].online >= 1 && sensor[s_Rain].value > 0 && limit.RainEN == ON)
  857. // {
  858. // if (chk_log_time)
  859. // {
  860. // LOG_I("CAW:雨控\n");
  861. // }
  862. // device_status.rain_status = 1;
  863. // return res_Rain;
  864. // }
  865. // if (device_status.rain_status && limit.RainEN == ON)
  866. // {
  867. // ctr_Collect_Fan(OFF);
  868. // ctr_lamp(OFF, 1);
  869. // ctr_lamp(OFF, 2);
  870. // if (chk_log_time)
  871. // {
  872. // LOG_I("CAW:雨控\n");
  873. // }
  874. // return res_Rain;
  875. // }
  876. // device_status.rain_status = 0;
  877. Check_TestFree();
  878. return res_ok;
  879. }
  880. extern uint8_t stopreflashTakePhoto;
  881. extern uint8_t holdon_stareflash;
  882. /**
  883. * @brief 刷新工作状态
  884. *
  885. */
  886. void ReflashWorkSta(void)
  887. {
  888. if (ws_now >= ws_typemax)
  889. {
  890. rt_kprintf("ReflashWorkSta illegl wstype\n");
  891. }
  892. if (holdon_stareflash)
  893. {
  894. return;
  895. }
  896. work_day_def work_day = {0};
  897. switch (ws_now)
  898. {
  899. case ws_standby:
  900. HMI_WRITE("workSta.workinfo.txt=\"待机中...\"");
  901. break;
  902. // res_ok = 0, // 没问题
  903. // res_Time, // 时控
  904. // res_Light, // 光控
  905. // res_TempH, // 温湿度
  906. // res_Rain // 雨控
  907. case ws_wait0:
  908. switch (Check_Allow_Work())
  909. {
  910. case res_ok:
  911. HMI_WRITE("workSta.workinfo.txt=\"达到工作条件\"");
  912. break;
  913. case res_Time:
  914. HMI_WRITE("workSta.workinfo.txt=\"未达工作条件 - 时控\"");
  915. break;
  916. case res_Light:
  917. HMI_WRITE("workSta.workinfo.txt=\"未达工作条件 - 光控\"");
  918. break;
  919. case res_Temp:
  920. HMI_WRITE("workSta.workinfo.txt=\"未达工作条件 - 温控\"");
  921. break;
  922. case res_Humi:
  923. HMI_WRITE("workSta.workinfo.txt=\"未达工作条件 - 湿控\"");
  924. break;
  925. case res_Temp_D:
  926. HMI_WRITE("workSta.workinfo.txt=\"未达工作条件 - 温控(基于定位)\"");
  927. break;
  928. case res_Humi_D:
  929. HMI_WRITE("workSta.workinfo.txt=\"未达工作条件 - 湿控 (基于定位)\"");
  930. break;
  931. case res_Rain:
  932. HMI_WRITE("workSta.workinfo.txt=\"未达工作条件 - 雨控\"");
  933. break;
  934. default:
  935. HMI_WRITE("workSta.workinfo.txt=\"未达到工作条件 %d\"", Check_Allow_Work());
  936. break;
  937. }
  938. break;
  939. case ws_start_coll:
  940. HMI_WRITE("workSta.workinfo.txt=\"STEP1:收集开始\"");
  941. break;
  942. case ws_wait_coll:
  943. HMI_WRITE("workSta.workinfo.txt=\"STEP2:等待收集完成 %d%%\"", GetCollInfo());
  944. break;
  945. case ws_takephoto:
  946. HMI_WRITE("workSta.workinfo.txt=\"STEP3:开始拍照\"");
  947. break;
  948. case ws_jumptake:
  949. HMI_WRITE("workSta.workinfo.txt=\"STEP4:采集中途退出 %d\"", Check_Allow_Work());
  950. break;
  951. case ws_flap:
  952. HMI_WRITE("workSta.workinfo.txt=\"STEP5:翻板中\"");
  953. break;
  954. case ws_once_finsh:
  955. HMI_WRITE("workSta.workinfo.txt=\"STEP6:单次工作循环结束\"");
  956. break;
  957. case ws_finsh:
  958. ef_get_env_blob("work_day", &work_day, sizeof(work_day), NULL);
  959. HMI_WRITE("workSta.workinfo.txt=\"今日工作周期结束 %02d.%02d.%02d\"", work_day.year % 100, work_day.month, work_day.day);
  960. break;
  961. default:
  962. break;
  963. }
  964. }
  965. static void SendReadInfo(void)
  966. {
  967. char *readinfo = makeJson_ReadInfo();
  968. DTU_Write("%s", readinfo);
  969. rt_kprintf("%s\n", readinfo);
  970. rt_free(readinfo);
  971. }
  972. /**
  973. * @brief Construct a new Updata_INR object
  974. *
  975. * @param type > enable power off
  976. */
  977. static uint16_t Updata_INR(uint8_t type)
  978. {
  979. static uint16_t rtuon_cnt = 0; // 非工作模式时 rtu上电时间记录
  980. static char Once_poweroff = 1;
  981. /**
  982. * @brief ↓↓↓ 不在工作模式的时候 间隔上线上报数据 在此处实现 ↓↓↓
  983. *
  984. */
  985. INR_DAT = device_status.dattim * 60;
  986. if (type == 0)
  987. {
  988. INR_DAT = device_status.dattim * 60;
  989. }
  990. wait_data_cnt++;
  991. if (wait_data_cnt >= INR_DAT || math_timestampe_NEW(&tm_data) > INR_DAT)
  992. {
  993. recode_timestampe_NEW(&tm_data); // 此时重置时间戳
  994. if (wait_data_cnt >= INR_DAT)
  995. {
  996. LOG_I(" >>> watting mode > STEP A start report data A\n");
  997. }
  998. else
  999. {
  1000. LOG_I(" >>> watting mode > STEP A start report data B\n");
  1001. }
  1002. wait_data_cnt = 0;
  1003. LOG_I(" >>> watting mode > STEP A start report data\n");
  1004. ctr_RTU_DTU(ON);
  1005. sprintf(device_status.net, "1"); // 去掉网络状态
  1006. while (++wait_data_cnt < WAIT_NET_MAX)
  1007. {
  1008. SendReadInfo();
  1009. if (atoi(device_status.net) == 0)
  1010. {
  1011. LOG_I(" >>> watting mode > STEP B1 RTU net get up\n");
  1012. rt_thread_mdelay(2000);
  1013. UpLoad_Data();
  1014. rt_thread_mdelay(30000); // 留有指令下发时间
  1015. break;
  1016. }
  1017. rt_thread_mdelay(1000);
  1018. }
  1019. if (wait_data_cnt >= WAIT_NET_MAX)
  1020. {
  1021. LOG_W(" >>> watting mode > STEP B2 RTU net get failed\n");
  1022. Recode_e_code(e_rtu_net_fail, 1, "间隔上报时联网失败 > B2");
  1023. }
  1024. wait_data_cnt = 0;
  1025. if (math_timestampe_NEW(&tm_photo) > (INR_PIC - 60) && (Check_Allow_Work() == res_ok)) // 接近图片上报 不再断电
  1026. {
  1027. LOG_I("CLOSE UP_PIC , JUMP RTU0");
  1028. }
  1029. else
  1030. {
  1031. ctr_RTU_DTU(OFF);
  1032. }
  1033. }
  1034. if (math_timestampe_NEW(&tm_data) == 0)
  1035. {
  1036. LOG_W("math_timestampe_NEW tm_data fail ,SET NOW");
  1037. }
  1038. /**
  1039. * @brief ↑↑↑ 不在工作模式的时候 间隔上线上报数据 在此处实现 ↑↑↑
  1040. *
  1041. */
  1042. /**
  1043. * @brief ↓↓↓ 首次上电后 留有三分钟数据上报 指令下发时间 ↓↓↓
  1044. *
  1045. */
  1046. if (rturead() && Once_poweroff)
  1047. {
  1048. rtuon_cnt++;
  1049. if (rtuon_cnt >= RTU_OFF_MAX)
  1050. {
  1051. LOG_I("RTU ON Time out of range , now turn it off A\n\n");
  1052. ctr_RTU_DTU(OFF);
  1053. rtuon_cnt = 0;
  1054. Once_poweroff = 0;
  1055. }
  1056. }
  1057. /**
  1058. * @brief ↑↑↑ 首次上电后 留有三分钟数据上报 指令下发时间 ↑↑↑
  1059. *
  1060. */
  1061. return wait_data_cnt;
  1062. }
  1063. void KeyTigCheck(void)
  1064. {
  1065. #define manual_mode_MX 60
  1066. #define demo_mode_MX 120
  1067. uint32_t cnt = 0;
  1068. if (ws_now == ws_KeyTig)
  1069. {
  1070. Recode_e_code(e_manual_mode, 0, "进入手动触发模式");
  1071. while (cnt++ < 60 * manual_mode_MX)
  1072. {
  1073. rt_thread_mdelay(1000);
  1074. if (ws_now != ws_KeyTig)
  1075. {
  1076. break;
  1077. }
  1078. rt_kprintf("处于手动触发模式 %d/%d\n", cnt, manual_mode_MX * 60);
  1079. }
  1080. Recode_e_code(e_manual_mode, 1, "退出手动触发模式");
  1081. }
  1082. if (syscfg.Demo_mode == 1)
  1083. {
  1084. Recode_e_code(e_demo_mode, 0, "进入演示模式");
  1085. cnt = 0;
  1086. rt_kprintf("演示模式 暂停工作 %d / %d\n", cnt, demo_mode_MX * 60);
  1087. while (cnt++ < demo_mode_MX * 60)
  1088. {
  1089. rt_thread_mdelay(1000);
  1090. if (syscfg.Demo_mode == 0)
  1091. {
  1092. break;
  1093. }
  1094. if (cnt % 100 == 0)
  1095. {
  1096. rt_kprintf("演示模式 暂停工作 %d / %d\n", cnt, demo_mode_MX * 60);
  1097. }
  1098. ws_now = ws_demo;
  1099. ctr_RTU_DTU(ON);
  1100. }
  1101. syscfg.Demo_mode = 0;
  1102. Recode_e_code(e_demo_mode, 1, "退出演示模式");
  1103. }
  1104. }
  1105. static void TigTakePho(void)
  1106. {
  1107. device_status.work_status = 3;
  1108. LOG_W("STEP3 :takephoto");
  1109. ctr_lamp(ON, 1); // 开诱捕灯
  1110. ctr_Collect_Fan(ON, 100); // 开风机
  1111. ws_now = ws_takephoto;
  1112. ctr_led(ON);
  1113. HMI_WRITE("sysTest.result.txt=\"立即拍照开始\"");
  1114. uint8_t b = 0;
  1115. for (b = 0; b < 180; b++)
  1116. {
  1117. if (atoi(device_status.net) == 0)
  1118. {
  1119. rt_kprintf("syscfg.rtu_sta check on\n");
  1120. break;
  1121. }
  1122. rt_thread_mdelay(1000);
  1123. SendReadInfo();
  1124. }
  1125. if (b >= 180)
  1126. {
  1127. rt_kprintf("syscfg.rtu_sta time out %d \n", b);
  1128. }
  1129. DTU_Write("takephoto.mp3");
  1130. Hk_Take_io();
  1131. char *takephotojson = makeJson_takephoto();
  1132. DTU_Write("%s", takephotojson);
  1133. rt_free(takephotojson);
  1134. uint8_t a = 0;
  1135. for (a = 0; a < 180; a++)
  1136. {
  1137. syscfg.not_poweroff = 1;
  1138. if (syscfg.photo_finsh)
  1139. {
  1140. syscfg.photo_finsh = 0;
  1141. rt_kprintf("syscfg.photo_finsh \n");
  1142. break;
  1143. }
  1144. rt_thread_mdelay(1000);
  1145. rt_kprintf("syscfg.photo >>> %d \n", a);
  1146. }
  1147. syscfg.not_poweroff = 0;
  1148. if (a >= 180)
  1149. {
  1150. rt_kprintf("syscfg.photo time out %d \n", a);
  1151. }
  1152. if (jts.switchled_test != ON)
  1153. {
  1154. ctr_led(OFF);
  1155. }
  1156. else
  1157. {
  1158. LOG_W("STEP4 :jump takephoto");
  1159. ws_now = ws_jumptake;
  1160. rt_thread_delay(3000);
  1161. ctr_lamp(OFF, 1); // 关诱捕灯
  1162. ctr_lamp(OFF, 2); // 关诱捕灯下
  1163. ctr_Collect_Fan(OFF, 0); // 关风机
  1164. if (jts.switchled_test != ON)
  1165. {
  1166. ctr_led(OFF);
  1167. }
  1168. }
  1169. takephoto_cnt = 0;
  1170. LOG_W("STEP5 :Flap");
  1171. ws_now = ws_flap;
  1172. Mtor_Control_ZP(mct_Foreward);
  1173. LOG_W("STEP6 :one cycle finsh");
  1174. ws_now = ws_once_finsh;
  1175. rt_thread_delay(5000);
  1176. }
  1177. /**
  1178. * @brief 小虫体工作流程
  1179. *
  1180. */
  1181. void WorkTask_XCT(void)
  1182. {
  1183. uint16_t log_en_inr = LOG_INR * 5; // 打印log的速度 数值越小 打印越频繁
  1184. static int16_t log_en_cnt = -1;
  1185. if (tm_data + tm_photo == 0 && GetDate.Year > 20)
  1186. {
  1187. recode_timestampe_NEW(&tm_data);
  1188. recode_timestampe_NEW(&tm_photo);
  1189. LOG_I("recode_timestampe INIT");
  1190. }
  1191. LOG_I(" WorkTask_XCT ");
  1192. if (Check_Allow_Work() != res_ok)
  1193. {
  1194. ctr_lamp(OFF, 1); // 关诱捕灯
  1195. ctr_lamp(OFF, 2); // 关诱捕灯下
  1196. ctr_Collect_Fan(OFF, syscfg.fan_speed); // 关风机
  1197. if (jts.switchled_test != ON)
  1198. {
  1199. ctr_led(OFF);
  1200. }
  1201. }
  1202. rt_thread_mdelay(1000);
  1203. while (Check_Allow_Work() != res_ok) // 新增数据上报逻辑(开启rtu 上报一次数据)
  1204. {
  1205. log_en_inr = LOG_INR * 5;
  1206. rt_thread_mdelay(1000);
  1207. KeyTigCheck();
  1208. ws_now = ws_wait0; // 待机
  1209. if (chk_log_time)
  1210. {
  1211. LOG_I("STEP0 :wait work start");
  1212. }
  1213. Updata_INR(1);
  1214. }
  1215. rt_thread_mdelay(1000);
  1216. char last_once = 0;
  1217. while (Check_Allow_Work() == res_ok)
  1218. {
  1219. LOG_W("STEP1 :start coll");
  1220. rt_thread_mdelay(2000);
  1221. ctr_lamp(ON, 1); // 开诱捕灯
  1222. ctr_Collect_Fan(ON, syscfg.fan_speed); // 开风机
  1223. device_status.work_status = 1;
  1224. device_status.traplampsta = 1;
  1225. (device_status.photim >= 5) ? (INR_PIC = (device_status.photim * 60)) : (INR_PIC = (TakeINR * 60));
  1226. rt_kprintf("takephoto_cnt %d inr %d \n", takephoto_cnt, INR_PIC);
  1227. while ((Check_Allow_Work() == res_ok) && (takephoto_cnt++ < (INR_PIC)))
  1228. {
  1229. (device_status.photim >= 5) ? (INR_PIC = (device_status.photim * 60)) : (INR_PIC = (TakeINR * 60));
  1230. if (chk_log_time)
  1231. {
  1232. LOG_W("STEP2 :wait coll finsh %d%%", GetCollInfo());
  1233. }
  1234. KeyTigCheck();
  1235. ws_now = ws_wait_coll;
  1236. rt_thread_mdelay(1000);
  1237. if (math_timestampe_NEW(&tm_photo) >= (INR_PIC)) // 拍照部分
  1238. {
  1239. recode_timestampe_NEW(&tm_photo);
  1240. LOG_I("Read to takephoto A\n");
  1241. last_once = 1;
  1242. ctr_RTU_DTU(ON);
  1243. TigTakePho();
  1244. takephoto_cnt = 0;
  1245. if (math_timestampe_NEW(&tm_data) > (INR_DAT - 30)) // 接近数据上报 不再断电
  1246. {
  1247. LOG_I("CLOSE UPDATA , JUMP RTU0");
  1248. }
  1249. else
  1250. {
  1251. ctr_RTU_DTU(OFF);
  1252. }
  1253. }
  1254. // else if ((takephoto_cnt >= ((INR_PIC) - WAIT_NET_MAX))) // 等待拍照部分
  1255. // {
  1256. // ctr_RTU_DTU(ON);
  1257. // }
  1258. else // 数据部分
  1259. {
  1260. Updata_INR(0);
  1261. }
  1262. // if (Get_percent() >= 50 && Get_percent() <= 100) 260403 关闭了过半关灯逻辑
  1263. // {
  1264. // if (rt_pin_read(LAMP_SW) == ON)
  1265. // {
  1266. // ctr_lamp(OFF, 1); // 进度过半 关上诱捕灯
  1267. // Recode_e_code(e_ctl_lamp, Get_percent(), "动态控制诱捕灯关");
  1268. // }
  1269. // }
  1270. // else if (Get_percent() < 50 && Get_percent() >= 0)
  1271. // {
  1272. // if (rt_pin_read(LAMP_SW) == OFF)
  1273. // {
  1274. // ctr_lamp(ON, 1); // 进度没有 恢复上诱捕灯
  1275. // Recode_e_code(e_ctl_lamp, Get_percent(), "动态控制诱捕灯开");
  1276. // }
  1277. // }
  1278. if (chk_log_time)
  1279. {
  1280. rt_kprintf("Get_percent() >> %d \n", Get_percent());
  1281. }
  1282. }
  1283. if (takephoto_cnt > (INR_PIC))
  1284. {
  1285. rt_kprintf("takephoto_cnt err area !\n");
  1286. takephoto_cnt = 0;
  1287. }
  1288. }
  1289. // 时控模式退出后 上报一次照片 需要间隔已经有至少一半
  1290. if ((GetCollInfo() >= 60 && last_once == 0) || (GetCollInfo() >= 95))
  1291. {
  1292. recode_timestampe_NEW(&tm_photo);
  1293. if (rt_pin_read(CAM_CTL) != ON || rt_pin_read(RTU_DTU) != ON)
  1294. {
  1295. rt_kprintf("检测到拍照前未开启RTU");
  1296. ctr_RTU_DTU(ON);
  1297. CTL_CAM1();
  1298. ctr_led(ON);
  1299. for (uint16_t a = 0; a < 45; a++)
  1300. {
  1301. rt_thread_mdelay(1000);
  1302. rt_kprintf("wait for RTU start A3\n");
  1303. }
  1304. }
  1305. LOG_I("Read to takephoto B\n");
  1306. ctr_RTU_DTU(ON);
  1307. TigTakePho();
  1308. takephoto_cnt = 0;
  1309. ctr_RTU_DTU(OFF);
  1310. CTL_CAM0();
  1311. ctr_led(OFF);
  1312. }
  1313. else
  1314. {
  1315. rt_kprintf("GetCollInfo %d last_once %d\n\n" , GetCollInfo() , last_once);
  1316. }
  1317. last_once = 0;
  1318. ctr_lamp(OFF, 1); // 关诱捕灯
  1319. ctr_lamp(OFF, 2); // 关诱捕灯下
  1320. ctr_Collect_Fan(OFF, syscfg.fan_speed); // 关风机
  1321. if (jts.switchled_test != ON)
  1322. {
  1323. ctr_led(OFF);
  1324. }
  1325. device_status.work_status = 0;
  1326. device_status.traplampsta = 0;
  1327. }
  1328. /********** RTU Power Ctl ************/
  1329. static void rtu1(void)
  1330. {
  1331. ctr_RTU_DTU(ON);
  1332. }
  1333. static void rtu0(void)
  1334. {
  1335. ctr_RTU_DTU(OFF);
  1336. }
  1337. static char rturead(void)
  1338. {
  1339. char res = rt_pin_read(RTU_DTU);
  1340. // res ? rt_kprintf("RTU power supply : ON\n") : rt_kprintf("RTU power supply : OFF\n");
  1341. return res;
  1342. }
  1343. static char readrtu(void)
  1344. {
  1345. char res = rt_pin_read(RTU_DTU);
  1346. res ? rt_kprintf("RTU power supply : ON\n") : rt_kprintf("RTU power supply : OFF\n");
  1347. return res;
  1348. }
  1349. MSH_CMD_EXPORT(rtu1, rtu1)
  1350. MSH_CMD_EXPORT(rtu0, rtu0)
  1351. MSH_CMD_EXPORT(readrtu, readrtu)
  1352. /********** RTU Power Ctl ************/
  1353. static void inr_dis(void)
  1354. {
  1355. rt_kprintf("DATA INR >>> %d / %d \n\n", wait_data_cnt, device_status.dattim * 60);
  1356. rt_kprintf("PHO INR >>> %d / %d \n\n", takephoto_cnt, device_status.photim * 60 - WAIT_NET_MAX);
  1357. }
  1358. MSH_CMD_EXPORT(inr_dis, inr_dis)
  1359. extern RTC_DateTypeDef GetDate;
  1360. extern RTC_TimeTypeDef GetTime;
  1361. extern uint8_t ReFlash_RTC(void);
  1362. static char temp[64] = {0};
  1363. #include "cJSON.h"
  1364. void status_Pri(uint8_t type)
  1365. {
  1366. // 创建根对象
  1367. cJSON *root = cJSON_CreateObject();
  1368. if (root == NULL)
  1369. {
  1370. return NULL;
  1371. }
  1372. // 添加 cmd 字段
  1373. cJSON_AddStringToObject(root, "cmd", "data");
  1374. // 创建 ext 对象
  1375. cJSON *ext = cJSON_CreateObject();
  1376. if (ext == NULL)
  1377. {
  1378. cJSON_Delete(root);
  1379. return NULL;
  1380. }
  1381. sprintf(temp, "%02d-%02d-%02d %02d:%02d:%02d",
  1382. GetDate.Year, GetDate.Month, GetDate.Date,
  1383. GetTime.Hours, GetTime.Minutes, GetTime.Seconds);
  1384. cJSON_AddStringToObject(ext, "当前时间", temp);
  1385. if (workmode != TypeMAX_wx)
  1386. {
  1387. cJSON_AddStringToObject(ext, "工作模式", WorkModeList[workmode].keyword);
  1388. }
  1389. switch (workmode)
  1390. {
  1391. case RunTime_wx:
  1392. sprintf(temp, "%d - %d", device_status.collecting_sh1, device_status.collecting_eh1);
  1393. cJSON_AddStringToObject(ext, "时控时间", temp);
  1394. break;
  1395. case RunLight_wx:
  1396. sprintf(temp, "%d", limit.LuxTime);
  1397. cJSON_AddStringToObject(ext, "光控时间", temp);
  1398. break;
  1399. default:
  1400. break;
  1401. }
  1402. sprintf(temp, "未在工作 %d ", Check_Allow_Work());
  1403. (Check_Allow_Work() == res_ok) ? cJSON_AddStringToObject(ext, "当前状态", "工作中") : cJSON_AddStringToObject(ext, "当前状态", temp);
  1404. sprintf(temp, "%d 分 (%d / %d)",
  1405. device_status.dattim,
  1406. math_timestampe_NEW(&tm_data), INR_DAT);
  1407. cJSON_AddStringToObject(ext, "数据间隔", temp);
  1408. sprintf(temp, "%d 分 (%d / %d)",
  1409. //syscfg.photim,
  1410. device_status.photim,
  1411. math_timestampe_NEW(&tm_photo), INR_PIC);
  1412. cJSON_AddStringToObject(ext, "照片间隔", temp);
  1413. // 将 ext 对象添加到根对象
  1414. cJSON_AddItemToObject(root, "ext", ext);
  1415. // 生成 JSON 字符串
  1416. char *json_str = cJSON_Print(root);
  1417. rt_kprintf("%s", json_str);
  1418. if (json_str != NULL)
  1419. free(json_str);
  1420. if (type == 0)
  1421. {
  1422. char *json_strU = cJSON_PrintUnformatted(root);
  1423. DTU_Write(json_strU);
  1424. if (json_strU != NULL)
  1425. free(json_strU);
  1426. }
  1427. // 清理
  1428. cJSON_Delete(root);
  1429. }
  1430. extern works_def ws_now;
  1431. static void status_(void)
  1432. {
  1433. rt_kprintf("ws_now > %d \n", ws_now);
  1434. rt_kprintf("lamp_up > %d \n", rt_pin_read(LAMP_SW));
  1435. rt_kprintf("lamp_dw > %d \n", rt_pin_read(LAMP_SW_DOWN));
  1436. status_Pri(1);
  1437. }
  1438. MSH_CMD_EXPORT(status_, status_);