core.c 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200
  1. /******************************************************************
  2. ** Copyright (c) 2009 Wuhan Mozit Technology Co., Ltd .
  3. ** FileName: core.c
  4. ** Author: BigHead
  5. ** Mail: jsrenyw@icloud.com
  6. ** Editor: bighead
  7. ** Date: 2020-11-10 13:34
  8. ** Version: 2020-11-10
  9. ** File Description: 业务逻辑核心代码实现部分
  10. ******************************************************************/
  11. #include "core.h"
  12. #include "cmd.h"
  13. //指令发送表device_command:
  14. #define CTR_RRS 1 //远程重启
  15. #define CTR_SFR 2 //设备恢复出厂设置
  16. #define CTR_RS 3 //服务器跳转
  17. #define CTR_OTA 4 //ota升级
  18. #define CTR_RDC 5 //远程手动调光
  19. #define CTR_RSC 6 //远程开关控制 需回复
  20. #define CTR_RCN 7 //删除子节点指令 需回复
  21. #define CFG_BKS 8 //备份服务器配置 需回复
  22. #define CFG_ULI 9 //设备数据上传间隔配置 需回复
  23. #define CFG_STS 10 //开关时间段设置 需回复
  24. #define CFG_SRV 11 //额定电压设置 需回复
  25. #define CFG_SRC 12 //额定电流设置 需回复
  26. #define CFG_NAT 13 //下发节点信息表配置
  27. #define CFG_GNV 14 //获取子节点版本号
  28. #define CFG_SCM 15 //开关控制模式(拉合闸)设置 需回复
  29. #define CFG_DGS 16 //调光节点分组设置
  30. #define CFG_DGM 17 //调光节点分组数据修改
  31. #define CFG_MGM 18 //电表节点分组设置 需回复
  32. #define CFG_SAT 19 //传感器报警阀值设置 需回复
  33. #define CTR_RGC 20 //远程开关编组控制 需回复
  34. //继电器状态:
  35. #define SW_ON 0 //0x0000:继电器合闸
  36. #define SW_MANUAL_CONTROL 32 //0x0020:继电器远程拉闸
  37. #define SW_TIMER_CONTROL 16 //0x0010: 继电器自动时间段拉闸
  38. #define SW_TEMPERATURE_HUMIDITY_ALARM 513 //0x0201:继电器温湿度报警拉闸 需报警
  39. #define SW_FIRE_ALARM 514 //0x0202:继电器烟感报警拉闸 需报警
  40. #define SW_TILT_ALARM 515 //0x0203:继电器倾斜报警拉闸 需报警
  41. #define SW_LOCK_ALARM 516 //0x0204:继电器锁具报警拉闸 需报警
  42. #define SW_LINE_TEMPERATURE_ALARM 517 //0x0205:继电器线温报警拉闸 需报警
  43. #define SW_OVERVOLTAGE 1 //0x0001:过压拉闸 需报警
  44. #define SW_UNDERVOLTAGE 2 //0x0002:欠压拉闸 需报警
  45. #define SW_OVERLOAD_ALARM 4 //0x0004: 过载拉闸 需报警
  46. #define SW_ELECTRIC_EXCESS 8 //0x0008:用电超额拉闸
  47. #define SW_OVER_SWITCH_OUT_COUNT 64 //0x0040:超自动合闸次数
  48. #define SW_FAST_CURRENT 128 //0x0080:快速电流拉闸
  49. int sw[] = {513,514,515,516,517,1,2,4};
  50. typedef enum {false = 0,true =1} bool;
  51. static pthread_t threads[32];
  52. #define CRC32_POLYNOMIAL 0xEDB88320
  53. list_node* file_list = NULL; //文件链表
  54. list_node* user_list = NULL; //设备链表
  55. int have_table = 0;
  56. static uint32_t crc_table32[256]; //CRC查询表
  57. unsigned short ota_file_packet_len = 1024;//ota文件每包的数据长度
  58. //按照大端模式解析数据
  59. //将1个整型数据填充到缓存中
  60. #define INT_TO_BUFF(buff, pos, val) \
  61. buff[(pos)] = (val)&0x000000FF; \
  62. buff[(pos) + 1] = ((val)&0x0000FF00) >> 8; \
  63. buff[(pos) + 2] = ((val)&0x00FF0000) >> 16; \
  64. buff[(pos) + 3] = ((val)&0xFF000000) >> 24
  65. //从缓存中提取1个整型数据
  66. #define INT_FROM_BUFF(buff, pos) ((buff[(pos) + 3] << 24) + (buff[(pos) + 2] << 16) + (buff[(pos) + 1] << 8) + buff[(pos)])
  67. //从缓存中提取1个整型数据
  68. #define SHORT_FROM_BUFF(buff, pos) ((buff[(pos) + 1] << 8) + buff[(pos)])
  69. /******************************************************************
  70. * Function Name: db_init
  71. * Arguments:
  72. * Return Value: void
  73. * Date: 2020-11-10
  74. * Editor: bighead
  75. * Description: 程序启动时刻,调用该初始化函数多次,初始化不同mysql 连接
  76. ******************************************************************/
  77. int db_init(MYSQL *db)
  78. {
  79. int ret = 1;
  80. if (db)
  81. {
  82. MYSQL *_db = db;
  83. ret = mysqlConnetInit(_db) ? 1 : 0;
  84. }
  85. else
  86. {
  87. elog("MYSQL.var is NULL \n ");
  88. exit(0);
  89. }
  90. return ret;
  91. }
  92. /******************************************************************
  93. * Function Name: core_init
  94. * Arguments:
  95. * Return Value: void
  96. * Date: 2020-11-10
  97. * Editor: bighead
  98. * Description: 程序启动时刻,调用该初始化函数仅 一次,该函数不允许重复调用
  99. ******************************************************************/
  100. int core_init(void)
  101. {
  102. int ret = 0;
  103. // 加载Topic服务配置
  104. initTopicConf();
  105. //创建队列
  106. //m_pque = CreateQueue(1000);
  107. // init mqtt.client
  108. init_mqtt_client();
  109. sleep(1);
  110. // 注册Topic
  111. regTopicFromTable();
  112. //创建处理任务队列线程
  113. //if(NUM_THREADS_UPLOAD_g>0)
  114. // CreateDbHandThread();
  115. return ret;
  116. }
  117. /******************************************************************
  118. * Function Name: core_heart
  119. * Arguments:
  120. * Return Value: void
  121. * Date: 2020-11-10
  122. * Editor: bighead
  123. * Description: 每次主线程心跳调用, 约200ms一次, 可以调整频率在decode.c
  124. ******************************************************************/
  125. int core_heart(unsigned int nowTime)
  126. {
  127. int ret=0;
  128. ret=nowTime;
  129. return ret;
  130. }
  131. /******************************************************************
  132. * Function Name: core_heart_1s
  133. * Arguments:
  134. * Return Value: void
  135. * Date: 2020-11-10
  136. * Editor: bighead
  137. * Description: 每次主线程心跳调用, 约1s一次,不超过2s, 在core_heart心跳函数之后调用
  138. * 可以调整频率在decode.c
  139. ******************************************************************/
  140. int core_heart_1s(unsigned int nowTime)
  141. {
  142. int ret = 0;
  143. ret = nowTime;
  144. //时间同步广播
  145. ret = TimeSyncBroadcast();
  146. //从数据库取指令
  147. SendCmdFromDb();
  148. return ret;
  149. }
  150. //初始化时候进行部分测试,可以随意添加
  151. int core_do_test(void)
  152. {
  153. //decode_msg_handle("TEST", NULL, NULL);
  154. print_stats();
  155. return 0;
  156. }
  157. //定期调用会话统计信息, 分钟级别
  158. int core_stats(void)
  159. {
  160. print_stats();
  161. return 0;
  162. }
  163. /******************************************************************
  164. * Function Name: core_alarm_gateway
  165. * Arguments:
  166. * Return Value: void
  167. * Date: 2023-12-5
  168. * Editor: cc
  169. * Description: 扫描网关设备数据
  170. ******************************************************************/
  171. int CoreAlarmGateway()
  172. {
  173. static MYSQL *conn = NULL;
  174. MYSQL_RES* res = NULL;
  175. MYSQL_ROW row;
  176. char query[1024] = {0};
  177. int row_count;
  178. if (!conn)
  179. {
  180. // 先申请内存再初始化
  181. conn = malloc(sizeof(MYSQL));
  182. db_init(conn);
  183. }
  184. sprintf(query,"SELECT t1.device_mac,t1.gateway_mac,t2.device_name,t2.control_mode,t1.update_time,"
  185. "t1.current_on_off,t1.current_electric,t1.original_relay,t2.swith_time1,t2.swith_time2,t2.swith_time3,t2.swith_time4,"
  186. "t2.electric_wave_set,t2.electric_wave_min,t2.electric_wave_max,t1.command_update_time "
  187. "FROM dev_status AS t1 "
  188. "INNER JOIN dev_info_gateway AS t2 "
  189. "ON t1.device_mac = t2.device_mac "
  190. "WHERE TIMESTAMPDIFF(MINUTE, t1.update_time, NOW()) < 10 "
  191. "AND t1.current_online=1 "
  192. "AND t1.original_relay IS NOT NULL "
  193. "AND t1.current_electric IS NOT NULL "
  194. "AND t1.electric_update_flag=1 ");
  195. excuteSql(conn,query);
  196. res = mysql_store_result(conn);
  197. if (NULL == res)
  198. {
  199. debug("NULL == res \n");
  200. return 1;
  201. }
  202. //获取行数
  203. row_count = mysql_num_rows(res);
  204. if(row_count<1)
  205. {
  206. mysql_free_result(res);
  207. debug("row_count<1 \n");
  208. return 1;
  209. }
  210. debug("CoreAlarmGateway row_count:%d \r\n",row_count);
  211. //循环取出
  212. while((row = mysql_fetch_row(res)))
  213. {
  214. char device_mac[30] = {0}; //0节点
  215. char gateway_mac[30] = {0}; //1网关
  216. char device_name[256] = {0}; //2设备名称
  217. int control_mode = 0; //3控制模式
  218. char update_time[20]; //4更新时间
  219. int current_on_off = 0; //5开关状态
  220. int current_electric = 0; //6电流
  221. int original_relay = 0; //7原始开关值
  222. char switch_time1[10] = {0}; //8开关时间1
  223. char switch_time2[10] = {0}; //9开关时间2
  224. char switch_time3[10] = {0}; //10开关时间3
  225. char switch_time4[10] = {0}; //11开关时间4
  226. int electric_wave_set = 0; //12电流波峰值
  227. double electric_wave_min = 0.0; //13电流波峰值
  228. double electric_wave_max = 0.0; //14电流波峰值
  229. char command_update_time[20]; //15指令更新时间
  230. struct tm tm_time;
  231. struct tm tm_time2;
  232. char timeString[20];
  233. int result,result1,result2,result3,result4;
  234. char update_sql[100]={0};
  235. char strTemp[256] ={0};
  236. //取出数据
  237. strcpy(device_mac,row[0]);
  238. strcpy(gateway_mac,row[1]);
  239. strcpy(device_name,row[2]);
  240. control_mode = atoi(row[3]);
  241. strptime(row[4], "%Y-%m-%d %H:%M:%S", &tm_time);
  242. strftime(update_time, sizeof(update_time), "%Y-%m-%d %H:%M:%S", &tm_time);
  243. current_on_off = atoi(row[5]);
  244. current_electric = atoi(row[6]);
  245. original_relay = atoi(row[7]);
  246. if(row[8]) strcpy(switch_time1,row[8]);
  247. if(row[9]) strcpy(switch_time2,row[9]);
  248. if(row[10]) strcpy(switch_time3,row[10]);
  249. if(row[11]) strcpy(switch_time4,row[11]);
  250. if(row[12]) electric_wave_set = atoi(row[12]);
  251. if(row[13]) electric_wave_min = atof(row[13]);
  252. if(row[14]) electric_wave_max = atof(row[14]);
  253. if(row[15]) strptime(row[15], "%Y-%m-%d %H:%M:%S", &tm_time2);
  254. strftime(command_update_time, sizeof(command_update_time), "%Y-%m-%d %H:%M:%S", &tm_time2);
  255. // log("CoreAlarmGateway : device_mac:'%s',gateway_mac:'%s',device_name:%s,control_mode:%d,update_time:%s,current_on_off:%d,"
  256. // "current_electric:%d,original_relay:%d,switch_time1:%s,switch_time2:%s,switch_time3:%s,switch_time4:%s,"
  257. // "electric_wave_set:%d,electric_wave_min:%f,electric_wave_max:%f \n",
  258. // device_mac,gateway_mac,device_name,control_mode,update_time,current_on_off,current_electric,original_relay,
  259. // switch_time1,switch_time2,switch_time3,switch_time4,electric_wave_set,electric_wave_min,electric_wave_max);
  260. //更新数据取出标记
  261. sprintf(update_sql,"update dev_status set electric_update_flag=2 where device_mac='%s' and gateway_mac='%s' ",device_mac,gateway_mac);
  262. excuteSql(conn,update_sql);
  263. //判断继电器数据
  264. result = RelayAlarm(gateway_mac,"0F0000000001",original_relay,conn);
  265. if(result==0) continue;
  266. //判断更新的数据是否在指令下发的2minute内
  267. if(row[15])
  268. {
  269. tm_time2.tm_min +=2; //将指令更新时间加2分钟
  270. mktime(&tm_time2);//重新计算时间
  271. int result = compareModifiedTimes(tm_time2,tm_time);
  272. if(result>=0)//指令更新时间在2分钟内跳过后续判断
  273. {
  274. debug("网关:%s,compareModifiedTimes tm_time2>=tm_time\n",device_name);
  275. continue;
  276. }
  277. }
  278. if(!row[8] && !row[9]) continue;
  279. strftime(timeString, sizeof(timeString), "%H:%M", &tm_time);
  280. debug("timeString:%s \n",timeString);
  281. //判断自动模式
  282. if(control_mode==0)
  283. {
  284. if(compareTimes(switch_time1,switch_time2)<=0)//switch_time1<switch_time2
  285. {
  286. debug("网关:%s,compareTimes switch_time1<switch_time2\n",device_name);
  287. result1 = compareTimes(switch_time1,timeString);
  288. result2 = compareTimes(timeString,switch_time2);
  289. debug("result1:%d,result2:%d \n",result1,result1);
  290. //合闸时间段继电器拉闸
  291. if (result1<=0 && result2<=0)
  292. {
  293. if(current_on_off==0)
  294. {
  295. debug("网关:%s,合闸时间段继电器拉闸 \n",device_name);
  296. int ret=ElectricAlarm(gateway_mac,"0F0000000001",device_name,device_name,1101,"合闸时间段继电器拉闸",conn);
  297. if(ret==0) continue;
  298. }
  299. }
  300. //拉闸时间段继电器合闸
  301. else
  302. {
  303. if(current_on_off==1)
  304. {
  305. debug("网关:%s,拉闸时间段继电器合闸 \n",device_name);
  306. int ret=ElectricAlarm(gateway_mac,"0F0000000001",device_name,device_name,1102,"拉闸时间段继电器合闸",conn);
  307. if(ret==0) continue;
  308. }
  309. }
  310. }
  311. else
  312. {
  313. debug("网关:%s,compareTimes switch_time1>switch_time2\n",device_name);
  314. result1 = compareTimes(switch_time1,timeString);
  315. result2 = compareTimes(timeString,switch_time2);
  316. debug("result1:%d,result2:%d \n",result1,result1);
  317. //合闸时间段
  318. if (result1<=0 || result2<=0)
  319. {
  320. debug("网关:%s,在合闸时间段 \n",device_name);
  321. if(current_on_off==0)
  322. {
  323. debug("网关:%s,合闸时间段继电器拉闸 \n",device_name);
  324. int ret=ElectricAlarm(gateway_mac,"0F0000000001",device_name,device_name,1101,"合闸时间段继电器拉闸",conn);
  325. if(ret==0) continue;
  326. }
  327. }
  328. //拉闸时间段
  329. else
  330. {
  331. debug("网关:%s,在拉闸时间段\n",device_name);
  332. if(current_on_off==1)
  333. {
  334. debug("网关:%s,拉闸时间段继电器合闸 \n",device_name);
  335. int ret=ElectricAlarm(gateway_mac,"0F0000000001",device_name,device_name,1102,"拉闸时间段继电器合闸",conn);
  336. if(ret==0) continue;
  337. }
  338. }
  339. }
  340. }
  341. //判断继电器拉闸状态有电流
  342. if(current_on_off==0 && current_electric>100)
  343. {
  344. debug("网关:%s,继电器拉闸状态有电流 \n",device_name);
  345. int ret=ElectricAlarm(gateway_mac,"0F0000000001",device_name,device_name,1103,"继电器拉闸状态有电流",conn);
  346. if(ret==0) continue;
  347. }
  348. //判断继电器合闸状态无电流
  349. if(current_on_off==1 && current_electric<100)
  350. {
  351. debug("网关:%s,继电器合闸状态无电流 \n",device_name);
  352. int ret=ElectricAlarm(gateway_mac,"0F0000000001",device_name,device_name,1104,"继电器合闸状态无电流",conn);
  353. if(ret==0) continue;
  354. }
  355. //判断继电器合闸状态电流偏离正常阈值
  356. if(current_on_off==1 && electric_wave_set==3)
  357. {
  358. double fcurrent_electric = current_electric/10000.0;
  359. if(fcurrent_electric<(electric_wave_min*0.9)|| fcurrent_electric>(electric_wave_max*1.1))
  360. {
  361. debug("网关:%s,继电器合闸状态电流偏离正常值 \n",device_name);
  362. sprintf(strTemp,"继电器合闸状态电流偏离正常值,当前值:%.3f,阈值:%.3f-%.3f",fcurrent_electric,electric_wave_min,electric_wave_max);
  363. int ret=ElectricAlarm(gateway_mac,"0F0000000001",device_name,device_name,1105,strTemp,conn);
  364. if(ret==0) continue;
  365. }
  366. }
  367. }
  368. mysql_free_result(res);
  369. return 0;
  370. }
  371. /******************************************************************
  372. * Function Name: core_alarm_gateway
  373. * Arguments:
  374. * Return Value: void
  375. * Date: 2023-12-8
  376. * Editor: cc
  377. * Description: 扫描节点设备数据
  378. ******************************************************************/
  379. int CoreAlarmNode()
  380. {
  381. static MYSQL *conn2 = NULL;
  382. MYSQL_RES* res = NULL;
  383. MYSQL_ROW row;
  384. char query[1024] = {0};
  385. int row_count;
  386. if (!conn2)
  387. {
  388. // 先申请内存再初始化
  389. conn2 = malloc(sizeof(MYSQL));
  390. db_init(conn2);
  391. }
  392. sprintf(query,"SELECT t1.device_mac,t1.gateway_mac,t3.device_name,t2.device_name,t2.control_mode,t1.update_time,t1.current_on_off,t1.current_electric,"
  393. "t1.original_relay,t2.swith_time1,t2.swith_time2,t2.swith_time3,t2.swith_time4,t2.electric_wave_set,t2.electric_wave_min,t2.electric_wave_max,t1.command_update_time "
  394. "FROM dev_status AS t1 "
  395. "INNER JOIN dev_info_node AS t2 "
  396. "ON t1.device_mac = t2.device_mac "
  397. "AND t1.gateway_mac=t2.gateway_mac "
  398. "INNER JOIN dev_info_gateway AS t3 "
  399. "ON t2.gateway_mac = t3.device_mac "
  400. "WHERE TIMESTAMPDIFF(MINUTE, t1.update_time, NOW()) < 10 "
  401. "AND t1.current_online=1 "
  402. "AND t1.original_relay IS NOT NULL "
  403. "AND t1.current_electric IS NOT NULL "
  404. "AND t1.electric_update_flag=1 ");
  405. excuteSql(conn2,query);
  406. res = mysql_store_result(conn2);
  407. if (NULL == res)
  408. {
  409. debug("NULL == res \n");
  410. return 1;
  411. }
  412. //获取行数
  413. row_count = mysql_num_rows(res);
  414. if(row_count<1)
  415. {
  416. mysql_free_result(res);
  417. debug("row_count<1 \n");
  418. return 1;
  419. }
  420. debug("CoreAlarmNode row_count:%d \r\n",row_count);
  421. //循环取出
  422. while((row = mysql_fetch_row(res)))
  423. {
  424. char device_mac[30] = {0}; //0节点
  425. char gateway_mac[30] = {0}; //1网关
  426. char gateway_name[256] = {0}; //2设备名称
  427. char node_name[256] = {0}; //3节点名称
  428. int control_mode = 0; //4控制模式
  429. char update_time[20]; //5更新时间
  430. int current_on_off = 0; //6开关状态
  431. int current_electric = 0; //7电流
  432. int original_relay = 0; //8原始开关值
  433. char switch_time1[10] = {0}; //9开关时间1
  434. char switch_time2[10] = {0}; //10开关时间2
  435. char switch_time3[10] = {0}; //11开关时间3
  436. char switch_time4[10] = {0}; //12开关时间4
  437. int electric_wave_set = 0; //13电流波峰值
  438. double electric_wave_min = 0.0; //14电流波峰值
  439. double electric_wave_max = 0.0; //15电流波峰值
  440. struct tm tm_time;
  441. struct tm tm_time2;
  442. char timeString[20];
  443. int result,result1,result2,result3,result4;
  444. char update_sql[100]={0};
  445. char strTemp[256] ={0};
  446. //取出数据
  447. strcpy(device_mac,row[0]);
  448. strcpy(gateway_mac,row[1]);
  449. strcpy(gateway_name,row[2]);
  450. strcpy(node_name,row[3]);
  451. control_mode = atoi(row[4]);
  452. strptime(row[5], "%Y-%m-%d %H:%M:%S", &tm_time);
  453. strftime(update_time, sizeof(update_time), "%Y-%m-%d %H:%M:%S", &tm_time);
  454. current_on_off = atoi(row[6]);
  455. current_electric = atoi(row[7]);
  456. original_relay = atoi(row[8]);
  457. if(row[9]) strcpy(switch_time1,row[9]);
  458. if(row[10]) strcpy(switch_time2,row[10]);
  459. if(row[11]) strcpy(switch_time3,row[11]);
  460. if(row[12]) strcpy(switch_time4,row[12]);
  461. if(row[13]) electric_wave_set = atoi(row[13]);
  462. if(row[14]) electric_wave_min = atof(row[14]);
  463. if(row[15]) electric_wave_max = atof(row[15]);
  464. if(row[16]) strptime(row[15], "%Y-%m-%d %H:%M:%S", &tm_time2);
  465. // log("CoreAlarmNode : device_mac:'%s',gateway_mac:'%s',gateway_name:%s,node_name:%s,control_mode:%d,update_time:%s,current_on_off:%d,"
  466. // "current_electric:%d,original_relay:%d,switch_time1:%s,switch_time2:%s,switch_time3:%s,switch_time4:%s,"
  467. // "electric_wave_set:%d,electric_wave_min:%f,electric_wave_max:%f \n",
  468. // device_mac,gateway_mac,gateway_name,node_name,control_mode,update_time,current_on_off,current_electric,original_relay,
  469. // switch_time1,switch_time2,switch_time3,switch_time4,electric_wave_set,electric_wave_min,electric_wave_max);
  470. //更新数据取出标记
  471. sprintf(update_sql,"update dev_status set electric_update_flag=2 where device_mac='%s' and gateway_mac='%s' ",device_mac,gateway_mac);
  472. excuteSql(conn2,update_sql);
  473. //判断继电器数据
  474. result = RelayAlarm(gateway_mac,device_mac,original_relay,conn2);
  475. if(result==0) continue;
  476. //判断更新的数据是否在指令下发的2minute内
  477. if(row[16])
  478. {
  479. tm_time2.tm_min +=2; //将指令更新时间加2分钟
  480. mktime(&tm_time2);//重新计算时间
  481. int result = compareModifiedTimes(tm_time2,tm_time);
  482. if(result>=0)//指令更新时间在2分钟内跳过后续判断
  483. {
  484. debug("网关:%s,节点:%s,compareModifiedTimes tm_time2>=tm_time\n",gateway_name,node_name);
  485. continue;
  486. }
  487. }
  488. if(!row[9] || !row[10] || !row[11] || !row[12]) continue;
  489. strftime(timeString, sizeof(timeString), "%H:%M", &tm_time);
  490. debug("timeString:%s \n",timeString);
  491. //判断自动模式
  492. if(control_mode==0)
  493. {
  494. int isInTime1 = 0;
  495. int isInTime2 = 0;
  496. if(row[9]&&row[10]&&(strlen(switch_time1)>4)&&(strlen(switch_time2)>4))//第1个时间段不为空
  497. {
  498. debug("网关:%s,节点:%s,strlen(switch_time1)=%d,strlen(switch_time2)=%d\n",gateway_name,node_name,strlen(switch_time1),strlen(switch_time2));
  499. result1 = compareTimes(switch_time1,timeString);
  500. result2 = compareTimes(timeString,switch_time2);
  501. //时间正常顺序
  502. if(compareTimes(switch_time1,switch_time2)<=0)
  503. {
  504. debug("网关:%s,节点:%s,compareTimes switch_time1<=switch_time2\n",gateway_name,node_name);
  505. //合闸时间段
  506. if (result1<=0 && result2<=0) isInTime1=1;
  507. }
  508. //时间非正常顺序
  509. else
  510. {
  511. debug("网关:%s,节点:%s,compareTimes switch_time1>=switch_time2\n",gateway_name,node_name);
  512. //合闸时间段
  513. if (result1<=0 || result2<=0) isInTime1=1;
  514. }
  515. }
  516. else //第1个时间段为空
  517. {
  518. isInTime1=2;
  519. }
  520. if(row[11]&&row[12]&&(strlen(switch_time3)>4)&&(strlen(switch_time4)>4))//第2个时间段不为空
  521. {
  522. debug("网关:%s,节点:%s,strlen(switch_time3)=%d,strlen(switch_time4)=%d\n",gateway_name,node_name,strlen(switch_time3),strlen(switch_time4));
  523. result3 = compareTimes(switch_time3,timeString);
  524. result4 = compareTimes(timeString,switch_time4);
  525. //时间正常顺序
  526. if(compareTimes(switch_time3,switch_time4)<=0)
  527. {
  528. debug("网关:%s,节点:%s,compareTimes switch_time3<=switch_time4\n",gateway_name,node_name);
  529. //合闸时间段
  530. if (result3<=0 && result4<=0) isInTime2=1;
  531. }
  532. //时间非正常顺序
  533. else
  534. {
  535. debug("网关:%s,节点:%s,compareTimes switch_time3>=switch_time4\n",gateway_name,node_name);
  536. //合闸时间段
  537. if (result3<=0 || result4<=0) isInTime2=1;
  538. }
  539. }
  540. else //第1个时间段为空
  541. {
  542. isInTime2=2;
  543. }
  544. if((isInTime1==1||isInTime2==1) && current_on_off==0)
  545. {
  546. debug("网关:%s,节点:%s,合闸时间段继电器拉闸 \n",gateway_name,node_name);
  547. int ret=ElectricAlarm(gateway_mac,device_mac,gateway_name,node_name,1101,"合闸时间段继电器拉闸",conn2);
  548. if(ret==0) continue;
  549. }
  550. else if((isInTime1==0||isInTime2==0) && current_on_off==1)
  551. {
  552. debug("网关:%s,节点:%s,拉闸时间段继电器合闸 \n",gateway_name,node_name);
  553. int ret=ElectricAlarm(gateway_mac,device_mac,gateway_name,node_name,1102,"拉闸时间段继电器合闸",conn2);
  554. if(ret==0) continue;
  555. }
  556. }
  557. //判断继电器拉闸状态有电流
  558. if(current_on_off==0 && current_electric>100)
  559. {
  560. debug("网关:%s,节点:%s,继电器拉闸状态有电流 \n",gateway_name,node_name);
  561. int ret=ElectricAlarm(gateway_mac,device_mac,gateway_name,node_name,1103,"继电器拉闸状态有电流",conn2);
  562. if(ret==0) continue;
  563. }
  564. //判断继电器合闸状态无电流
  565. if(current_on_off==1 && current_electric<100)
  566. {
  567. debug("网关:%s,节点:%s,继电器合闸状态无电流 \n",gateway_name,node_name);
  568. int ret=ElectricAlarm(gateway_mac,device_mac,gateway_name,node_name,1104,"继电器合闸状态无电流",conn2);
  569. if(ret==0) continue;
  570. }
  571. //判断继电器合闸状态电流偏离正常阈值
  572. if(current_on_off==1 && electric_wave_set==3)
  573. {
  574. double fcurrent_electric = current_electric/10000.0;
  575. if(fcurrent_electric<(electric_wave_min*0.9)|| fcurrent_electric>(electric_wave_max*1.1))
  576. {
  577. debug("网关:%s,节点:%s,继电器合闸状态电流偏离正常值 \n",gateway_name,node_name);
  578. sprintf(strTemp,"继电器合闸状态电流偏离正常值,当前值:%.3f,阈值:%.3f-%.3f",fcurrent_electric,electric_wave_min,electric_wave_max);
  579. int ret=ElectricAlarm(gateway_mac,device_mac,gateway_name,node_name,1105,strTemp,conn2);
  580. if(ret==0) continue;
  581. }
  582. }
  583. }
  584. mysql_free_result(res);
  585. return 0;
  586. }
  587. /******************************************************************
  588. * Function Name: ElectricAlarm
  589. * Arguments:
  590. * Return Value: void
  591. * Date: 2023-12-7
  592. * Editor: cc
  593. * Description: 电流数据告警判断
  594. ******************************************************************/
  595. int ElectricAlarm(char* mac,char* subMac,char* gatewayName,char* nodeName,int alarmCode,char* alarmStr,MYSQL* _db)
  596. {
  597. //判断是否需要报警
  598. MYSQL_RES* res = NULL;
  599. MYSQL_ROW row;
  600. char querySql[256] = {0};
  601. char strName[256] = {0};
  602. char strAlarm[512] = {0};
  603. char updateSql[1024] = {0};
  604. char insertSql[512] = {0};
  605. int affectedRows = 0;
  606. int queryRow = 0;
  607. int fault_state=0;
  608. int fault_count=0;
  609. struct tm tm_time;
  610. //网关或节点名称
  611. if (strcmp(subMac,"0F0000000001") == 0)//网关
  612. {
  613. sprintf(strName,"设备名称:%s",gatewayName);
  614. }
  615. else
  616. {
  617. sprintf(strName,"设备名称:%s,节点:%s",gatewayName,nodeName);
  618. }
  619. //格式化报警内容
  620. sprintf(strAlarm,"%s,%s,时间:%s \r\n",strName,alarmStr,GetCurrentTime());
  621. //查询当前报警类型是否正在报警 fault_state 1: 未处理 2: 故障正在处理中 3: 处理完成
  622. sprintf(querySql,"select fault_state,fault_count,fault_time from dev_fault where device_mac = '%s' and device_mac_node = '%s' and relay_code = %d ",mac,subMac,alarmCode);
  623. excuteSql(_db,querySql);
  624. res = mysql_store_result(_db);
  625. queryRow = mysql_num_rows(res);
  626. if (res && queryRow>0)//有记录
  627. {
  628. debug("res && queryRow>0 querySql:%s\n",querySql);
  629. row = mysql_fetch_row(res);
  630. fault_state = atoi(row[0]);
  631. fault_count = atoi(row[1]);
  632. if(row[2]) strptime(row[2], "%Y-%m-%d %H:%M:%S", &tm_time);
  633. debug("fault_state:%d fault_count:%d\n",fault_state,fault_count);
  634. if(fault_state == 1 || fault_state == 2)//正在报警
  635. {
  636. log("查询到当前报警类型正在报警,不再重复报警,alarmStr:%s\n",strAlarm);
  637. mysql_free_result(res);
  638. return 1;
  639. }
  640. if(alarmCode>1100)//电流报警进行3次判断
  641. {
  642. //在更新次数前检查是否是连续的告警次数,否则重新计数,通过检查上一次告警时间是否在5min以内
  643. if(row[2])
  644. {
  645. tm_time.tm_min +=5; //将指令更新时间加5分钟
  646. mktime(&tm_time);//重新计算时间
  647. int result=compareWithCurrentTime(tm_time);
  648. if(result>=0)//如果在5min以内
  649. {
  650. if(fault_count >= 2)//加上本次报警次数达到3次
  651. {
  652. //更新到报警故障表
  653. sprintf(updateSql,"update dev_fault set fault_details = '%s',fault_state = 1,fault_time = now(),fault_count=0 where "
  654. "device_mac = '%s' and device_mac_node = '%s' and relay_code = %d",strAlarm,mac,subMac,alarmCode);
  655. log("触发告警(电流): %s\n",strAlarm);
  656. }
  657. else
  658. {
  659. fault_count = fault_count + 1;
  660. //更新报警次数,并不报警
  661. sprintf(updateSql,"update dev_fault set fault_details = '%s',fault_state = 3,fault_time = now(),fault_count=%d where "
  662. "device_mac = '%s' and device_mac_node = '%s' and relay_code = %d",strAlarm,fault_count,mac,subMac,alarmCode);
  663. debug("网关:%s,节点:%s,电流告警更新次数(不报警)\n",gatewayName,nodeName);
  664. }
  665. }
  666. else//不在5min以内 计数重新开始
  667. {
  668. //更新到报警故障表
  669. sprintf(updateSql,"update dev_fault set fault_details = '%s',fault_state = 3,fault_time = now(),fault_count=1 where "
  670. "device_mac = '%s' and device_mac_node = '%s' and relay_code = %d",strAlarm,mac,subMac,alarmCode);
  671. debug("不在5min以内 计数重新开始(电流): %s\n",strAlarm);
  672. }
  673. }
  674. else //没有时间字段 计数重新开始
  675. {
  676. //更新到报警故障表
  677. sprintf(updateSql,"update dev_fault set fault_details = '%s',fault_state = 3,fault_time = now(),fault_count=1 where "
  678. "device_mac = '%s' and device_mac_node = '%s' and relay_code = %d",strAlarm,mac,subMac,alarmCode);
  679. debug("没有时间字段 计数重新开始(电流): %s\n",strAlarm);
  680. }
  681. }
  682. else
  683. {
  684. //更新到报警故障表
  685. sprintf(updateSql,"update dev_fault set fault_details = '%s',fault_state = 1,fault_time = now() where "
  686. "device_mac = '%s' and device_mac_node = '%s' and relay_code = %d",strAlarm,mac,subMac,alarmCode);
  687. log("触发告警: %s\n",strAlarm);
  688. }
  689. debug("updateSql: %s\n",updateSql);
  690. excuteSql(_db,updateSql);
  691. }
  692. else//没有查询到记录
  693. {
  694. debug("没有记录 querySql:%s",querySql);
  695. sprintf(insertSql,"insert into dev_fault(device_mac,device_mac_node,fault_details,relay_code,fault_state,fault_time)values('%s','%s','%s',%d,1,now())",
  696. mac,subMac,strAlarm,alarmCode);
  697. log("触发告警(插入): %s\n",strAlarm);
  698. excuteSql(_db,insertSql);
  699. }
  700. mysql_free_result(res);
  701. // //更新到报警故障表
  702. // sprintf(updateSql,"update dev_fault set fault_details = '%s',fault_state = 1,fault_time = now() where "
  703. // "device_mac = '%s' and device_mac_node = '%s' and relay_code = %d",strAlarm,mac,subMac,alarmCode);
  704. // excuteSql(_db,updateSql);
  705. // affectedRows = mysql_affected_rows(_db);
  706. // if (affectedRows < 1)
  707. // {
  708. // sprintf(insertSql,"insert into dev_fault(device_mac,device_mac_node,fault_details,relay_code,fault_state,fault_time)values('%s','%s','%s',%d,1,now())",
  709. // mac,subMac,strAlarm,alarmCode);
  710. // //log("strAlarm:%s\n",strAlarm);
  711. // excuteSql(_db,insertSql);
  712. // }
  713. return 0;
  714. }
  715. //扫描数据库发送指令
  716. int SendCmdFromDb(void)
  717. {
  718. static MYSQL *_db = NULL;
  719. MYSQL_RES* res = NULL;
  720. MYSQL_ROW row;
  721. char query[1024] = {0};
  722. char deleteSql[256] = {0};
  723. char updateSql[256] = {0};
  724. int row_count;
  725. if (!_db)
  726. {
  727. // 先申请内存再初始化
  728. _db = malloc(sizeof(MYSQL));
  729. db_init(_db);
  730. }
  731. sprintf(query,"select id,device_mac,device_mac_node,device_command,device_group,device_on_off,"
  732. "device_luminance,dimming_mode,node_type,control_mode from dev_cmd_send where device_mac is not null and current_online = 1 and device_type < 10");
  733. excuteSql(_db,query);
  734. res = mysql_store_result(_db);
  735. if (NULL == res)
  736. {
  737. return 1;
  738. }
  739. //获取行数
  740. row_count = mysql_num_rows(res);
  741. if(row_count<1)
  742. {
  743. //debug("%s 没有查询到指令 \n",mac);
  744. mysql_free_result(res);
  745. return 1;
  746. }
  747. //循环取出
  748. while((row = mysql_fetch_row(res)))
  749. {
  750. int id = 0;
  751. char device_mac[30] = {0}; //网关mac 1
  752. char device_mac_node[30] = {0}; //节点mac 2
  753. int device_command = 0; //指令类型 3
  754. int device_group = 0; //组号 4
  755. int device_on_off = 0; //开关 5
  756. int device_luminance = 0; //亮度 6
  757. int dimming_mode = 0; //调光类型 7
  758. int node_type = 0; //节点类型 8
  759. int control_mode = 0; //开关控制模式 9
  760. int ret = 0;
  761. if(row[0])
  762. id = atoi(row[0]);
  763. if(!row[1] || strlen((char*)row[1])!=24)
  764. {
  765. //删除指令
  766. sprintf(deleteSql,"delete from dev_cmd_send where id = %d",id);
  767. excuteSql(_db,deleteSql);
  768. debug("网关mac不正确!");
  769. continue;
  770. }
  771. strcpy(device_mac,row[1]);
  772. if(row[2])
  773. strcpy(device_mac_node,row[2]);
  774. if(row[3])
  775. device_command = atoi(row[3]);
  776. if(row[4])
  777. device_group = atoi(row[4]);
  778. if(row[5])
  779. device_on_off = atoi(row[5]);
  780. if(row[6])
  781. device_luminance = atoi(row[6]);
  782. if(row[7])
  783. dimming_mode = atoi(row[7]);
  784. if(row[8])
  785. node_type = atoi(row[8]);
  786. if(row[9])
  787. control_mode = atoi(row[9]);
  788. debug("SendCmdFromDb 行数:%d ,device_mac:'%s',device_mac_node:'%s',device_command:%d,device_group:%d,device_on_off:%d,"
  789. "device_luminance:%d,dimming_mode:%d,node_type:'%d',control_mode:%d \n",
  790. row_count,device_mac,device_mac_node,device_command,device_group,device_on_off,device_luminance,dimming_mode,node_type,control_mode);
  791. //删除指令
  792. sprintf(deleteSql,"delete from dev_cmd_send where id = %d",id);
  793. excuteSql(_db,deleteSql);
  794. switch (device_command)
  795. {
  796. case CTR_RRS: //远程重启
  797. {
  798. ret = SendRestart(device_mac);
  799. }
  800. break;
  801. case CTR_SFR: //设备恢复出厂设置
  802. {
  803. ret = SendFactoryReset(device_mac);
  804. }
  805. break;
  806. case CTR_RS: //服务器跳转
  807. {
  808. ret = SendServerJump(device_mac,_db);
  809. }
  810. break;
  811. case CTR_OTA: //ota升级
  812. {
  813. ret = SendRemoteUpgrade(device_mac,_db);
  814. }
  815. break;
  816. case CTR_RDC: //远程手动调光
  817. {
  818. if(row[4] && row[6]) //row[7] 调光类型判断暂去掉
  819. {
  820. ret = SendManualDimming(device_mac,device_group,device_luminance,dimming_mode);
  821. }
  822. }
  823. break;
  824. case CTR_RSC: //远程开关控制 需回复
  825. {
  826. if (row[2] && (strlen(device_mac_node) == 12) && row[5] && row[8]) //节点
  827. {
  828. ret = SendSwitchControl(device_mac,device_mac_node,node_type,device_on_off);
  829. sprintf(updateSql,"update dev_status set command_update_time = now() where gateway_mac = '%s' and device_mac='%s'",device_mac,device_mac_node);
  830. }
  831. else if(!row[2] && row[5] && row[8]) //网关
  832. {
  833. ret = SendSwitchControl(device_mac,"",node_type,device_on_off);
  834. sprintf(updateSql,"update dev_status set command_update_time = now() where gateway_mac = '%s' and device_mac='%s'",device_mac,device_mac);
  835. }
  836. if(ret == 0)
  837. {
  838. excuteSql(_db,updateSql);
  839. }
  840. }
  841. break;
  842. case CTR_RCN: //删除子节点指令 需回复
  843. {
  844. if(row[2] && (strlen(device_mac_node) == 12) && row[8])
  845. {
  846. ret = SendDeleteNode(device_mac,device_mac_node,node_type);
  847. }
  848. }
  849. break;
  850. case CFG_BKS: //备份服务器配置 需回复
  851. {
  852. ret = SendBakIP(device_mac,_db);
  853. }
  854. break;
  855. case CFG_ULI: //设备数据上传间隔配置 需回复
  856. {
  857. ret = SendDataInterval(device_mac,_db);
  858. }
  859. break;
  860. case CFG_STS: //开关时间段设置 需回复
  861. {
  862. if (row[2] && (strlen(device_mac_node) == 12)) //节点
  863. {
  864. ret = SendOnOffTimeMuilt(device_mac,device_mac_node,_db);
  865. sprintf(updateSql,"update dev_status set command_update_time = now() where gateway_mac = '%s' and device_mac='%s'",device_mac,device_mac_node);
  866. }
  867. else if(!row[2]) //网关
  868. {
  869. ret = SendOnOffTimeMuilt(device_mac,"",_db);
  870. sprintf(updateSql,"update dev_status set command_update_time = now() where gateway_mac = '%s' and device_mac='%s'",device_mac,device_mac);
  871. }
  872. if(ret == 0)
  873. {
  874. excuteSql(_db,updateSql);
  875. }
  876. }
  877. break;
  878. case CFG_SRV: //额定电压设置 需回复
  879. {
  880. if (row[2] && (strlen(device_mac_node) == 12)) //节点
  881. {
  882. ret = SendRatedVoltage(device_mac,device_mac_node,_db);
  883. }
  884. else if(!row[2]) //网关
  885. {
  886. ret = SendRatedVoltage(device_mac,"",_db);
  887. }
  888. }
  889. break;
  890. case CFG_SRC: //额定电流设置 需回复
  891. {
  892. if (row[2] && (strlen(device_mac_node) == 12)) //节点
  893. {
  894. ret = SendRatedCurrent(device_mac,device_mac_node,_db);
  895. }
  896. else if(!row[2]) //网关
  897. {
  898. ret = SendRatedCurrent(device_mac,"",_db);
  899. }
  900. }
  901. break;
  902. case CFG_NAT: //下发节点信息表配置
  903. {
  904. ret = SendSubInfo(device_mac,_db);
  905. }
  906. break;
  907. case CFG_GNV: //获取子节点版本号
  908. {
  909. if (row[2] && (strlen(device_mac_node) == 12)) //节点
  910. {
  911. ret = SendGetSubVersion(device_mac,device_mac_node);
  912. }
  913. }
  914. break;
  915. case CFG_SCM: //开关控制模式(拉合闸)设置 需回复
  916. {
  917. if (row[2] && (strlen(device_mac_node) == 12)) //节点
  918. {
  919. ret = SendSwitchModeFromDB(device_mac,device_mac_node,_db);
  920. }
  921. else if(!row[2]) //网关
  922. {
  923. ret = SendSwitchModeFromDB(device_mac,"",_db);
  924. }
  925. }
  926. break;
  927. case CFG_DGS: //调光节点分组设置
  928. {
  929. if (row[2] && (strlen(device_mac_node) == 12)) //节点
  930. {
  931. ret = SendDimmingNodeGroup(device_mac,device_mac_node,_db);
  932. }
  933. }
  934. break;
  935. case CFG_DGM: //调光节点分组数据修改
  936. {
  937. if(row[4])
  938. {
  939. ret = SendDimmingNodeGroupModify(device_mac,device_group,_db);
  940. }
  941. }
  942. break;
  943. case CFG_MGM: //电表节点分组设置 需回复
  944. {
  945. }
  946. break;
  947. case CFG_SAT: //传感器报警阀值设置 需回复
  948. {
  949. ret = SendSensorThreshold(device_mac,_db);
  950. }
  951. break;
  952. case CTR_RGC: //远程开关编组控制 需回复
  953. {
  954. if(row[4] && row[5])
  955. {
  956. ret = SendSwitchGroupControl(device_mac,device_group,2,device_on_off);
  957. }
  958. }
  959. break;
  960. default:
  961. debug("指令不能识别:%d",device_command);
  962. break;
  963. }
  964. }
  965. mysql_free_result(res);
  966. return 0;
  967. }
  968. //时间同步广播
  969. int TimeSyncBroadcast(void)
  970. {
  971. //TIME_SYNC_INTERVAL_g 配置文件读取
  972. if(timeGloble_g%TIME_SYNC_INTERVAL_g==0)
  973. {
  974. int ret = 0;
  975. ret = SendNTP("");
  976. debug("时间同步广播结果:%d,当前时间同步间隔 %d \n",ret,TIME_SYNC_INTERVAL_g);
  977. }
  978. return 0;
  979. }
  980. //1.字节流转换为十六进制字符串
  981. void ByteToHexStr(const unsigned char* source, char* dest, int sourceLen)
  982. {
  983. short i;
  984. unsigned char highByte, lowByte;
  985. for (i = 0; i < sourceLen; i++)
  986. {
  987. highByte = source[i] >> 4;
  988. lowByte = source[i] & 0x0f ;
  989. highByte += 0x30;
  990. if (highByte > 0x39)
  991. dest[i * 2] = highByte + 0x07;
  992. else
  993. dest[i * 2] = highByte;
  994. lowByte += 0x30;
  995. if (lowByte > 0x39)
  996. dest[i * 2 + 1] = lowByte + 0x07;
  997. else
  998. dest[i * 2 + 1] = lowByte;
  999. }
  1000. return ;
  1001. }
  1002. //2.字节流转换为十六进制字符串
  1003. void Hex2Str( const char *sSrc, char *sDest, int nSrcLen )
  1004. {
  1005. int i;
  1006. char szTmp[3];
  1007. for( i = 0; i < nSrcLen; i++ )
  1008. {
  1009. sprintf( szTmp, "%02X", (unsigned char) sSrc[i] );
  1010. memcpy( &sDest[i * 2], szTmp, 2 );
  1011. }
  1012. return ;
  1013. }
  1014. //十六进制字符串转换为字节流
  1015. void HexStrToByte(const char* source, unsigned char* dest, int sourceLen)
  1016. {
  1017. short i;
  1018. unsigned char highByte, lowByte;
  1019. for (i = 0; i < sourceLen; i += 2)
  1020. {
  1021. highByte = toupper(source[i]);
  1022. lowByte = toupper(source[i + 1]);
  1023. if (highByte > 0x39)
  1024. highByte -= 0x37;
  1025. else
  1026. highByte -= 0x30;
  1027. if (lowByte > 0x39)
  1028. lowByte -= 0x37;
  1029. else
  1030. lowByte -= 0x30;
  1031. dest[i / 2] = (highByte << 4) | lowByte;
  1032. }
  1033. return ;
  1034. }
  1035. //改变字节顺序
  1036. void EndianSwap(unsigned char *pData, int startIndex, int length)
  1037. {
  1038. int i,cnt,end,start;
  1039. cnt = length / 2;
  1040. start = startIndex;
  1041. end = startIndex + length - 1;
  1042. unsigned char tmp;
  1043. for (i = 0; i < cnt; i++)
  1044. {
  1045. tmp = pData[start+i];
  1046. pData[start+i] = pData[end-i];
  1047. pData[end-i] = tmp;
  1048. }
  1049. return ;
  1050. }
  1051. //获取当前月份历史表
  1052. char* GetCurrentNYTable(void)
  1053. {
  1054. time_t t = time(0);
  1055. static char str[64] = {0};
  1056. strftime(str,sizeof(str),"dev_status_history_%Y%m",localtime(&t));
  1057. return str;
  1058. }
  1059. //获取系统时间年月日 时分秒
  1060. char* GetCurrentTime(void)
  1061. {
  1062. time_t t = time(0);
  1063. static char str[64] = {0};
  1064. strftime(str,sizeof(str),"%Y%m%d %H:%M:%S",localtime(&t));
  1065. return str;
  1066. }
  1067. //字符串中查找指定字符的个数
  1068. int find_char(char str[], char substr[])
  1069. {
  1070. int count = 0,i,j,check;
  1071. int len = strlen(str);
  1072. int sublen = strlen(substr);
  1073. for(i = 0; i < len; i++)
  1074. {
  1075. check = 1;
  1076. for(j = 0; j + i < len && j < sublen; j++)
  1077. {
  1078. if(str[i+j] != substr[j])
  1079. {
  1080. check = 0;
  1081. break;
  1082. }
  1083. }
  1084. if(check == 1)
  1085. {
  1086. count++;
  1087. i = i + sublen;
  1088. }
  1089. }
  1090. return count;
  1091. }
  1092. //从主题中查找指定'/'分割的段
  1093. char* find_string(char* topicName, int section)
  1094. {
  1095. static char tmp[50][50];
  1096. memset(tmp,0x0,2500);
  1097. char* p1 = (char*)malloc(1024);
  1098. int i = 0;
  1099. while ((p1 = strchr(topicName, '/')) != NULL)
  1100. {
  1101. strncpy(tmp[i], topicName,strlen(topicName)-strlen(p1));
  1102. topicName = p1 + 1;
  1103. i++;
  1104. }
  1105. strncpy(tmp[i], topicName, strlen(topicName));
  1106. free(p1);
  1107. return tmp[section];
  1108. }
  1109. //判断是否属于报警code
  1110. int IsRelayAlarmCode(int relayCode)
  1111. {
  1112. int i = 0;
  1113. for(i = 0;i<(int)(sizeof(sw)/sizeof(int));i++)
  1114. {
  1115. if(relayCode == sw[i])
  1116. return 1;
  1117. }
  1118. return -1;
  1119. }
  1120. //继电器报警
  1121. int RelayAlarm(char* mac,char* subMac,int relayCode,MYSQL* _db)
  1122. {
  1123. MYSQL_RES* res = NULL;
  1124. MYSQL_ROW row;
  1125. char querySql[256] = {0};
  1126. char updateSql[256] = {0};
  1127. char insertSql[256] = {0};
  1128. char strAlarm[256] = {0};
  1129. bool isExist = false;
  1130. char strAlarmType[256] = {0};
  1131. char strName[256] = {0};
  1132. char macName[256] = {0};
  1133. char subMacName[256] = {0};
  1134. int affectedRows = 0;
  1135. int queryRow = 0;
  1136. //判断是否需要报警
  1137. int i = 0;
  1138. for(i = 0;i<(int)(sizeof(sw)/sizeof(int));i++)
  1139. {
  1140. if(relayCode == sw[i])
  1141. isExist = true;
  1142. }
  1143. if(!isExist)
  1144. return 1;
  1145. //查询当前报警类型是否正在报警 fault_state 1: 未处理 2: 故障正在处理中 3: 处理完成
  1146. sprintf(querySql,"select * from dev_fault where device_mac = '%s' and device_mac_node = '%s' and relay_code = %d and (fault_state = 1 or fault_state = 2)",mac,subMac,relayCode);
  1147. excuteSql(_db,querySql);
  1148. res = mysql_store_result(_db);
  1149. queryRow = mysql_num_rows(res);
  1150. if (res && queryRow>0)
  1151. {
  1152. //debug("res && queryRow>0 querySql:%s",querySql);
  1153. mysql_free_result(res);
  1154. return 1;
  1155. }
  1156. mysql_free_result(res);
  1157. //查询网关节点名称
  1158. if (strcmp(subMac,"0F0000000001") == 0)//网关
  1159. {
  1160. sprintf(querySql,"select device_name from dev_info_gateway where device_mac = '%s' ",mac);
  1161. excuteSql(_db,querySql);
  1162. res = mysql_store_result(_db);
  1163. if (NULL == res)
  1164. {
  1165. return 1;
  1166. }
  1167. row = mysql_fetch_row(res);
  1168. if (NULL == row)
  1169. {
  1170. mysql_free_result(res);
  1171. return 1;
  1172. }
  1173. if(!row[0])
  1174. {
  1175. debug("device_name 为空");
  1176. mysql_free_result(res);
  1177. return 1;
  1178. }
  1179. strcpy(macName,row[0]);
  1180. sprintf(strName,"设备名称:%s",macName);
  1181. mysql_free_result(res);
  1182. }
  1183. else
  1184. {
  1185. sprintf(querySql,"select a.device_name as 'gateway_name',b.device_name as 'node_name' from dev_info_gateway a,dev_info_node b "
  1186. "where a.device_mac = b.gateway_mac and b.gateway_mac = '%s' and b.device_mac = '%s'",mac,subMac);
  1187. excuteSql(_db,querySql);
  1188. res = mysql_store_result(_db);
  1189. if (NULL == res)
  1190. {
  1191. return 1;
  1192. }
  1193. row = mysql_fetch_row(res);
  1194. if (NULL == row)
  1195. {
  1196. mysql_free_result(res);
  1197. return 1;
  1198. }
  1199. if(!row[0] || !row[1])
  1200. {
  1201. debug("gateway_name 或者 node_name 为空 ");
  1202. mysql_free_result(res);
  1203. return 1;
  1204. }
  1205. strcpy(macName,row[0]);
  1206. strcpy(subMacName,row[1]);
  1207. mysql_free_result(res);
  1208. sprintf(strName,"设备:%s,节点:%s",macName,subMacName);
  1209. }
  1210. //判断报警类型
  1211. if(relayCode == SW_TEMPERATURE_HUMIDITY_ALARM)
  1212. {
  1213. strcpy(strAlarmType,"温湿度报警拉闸");
  1214. }
  1215. else if(relayCode == SW_FIRE_ALARM)
  1216. {
  1217. strcpy(strAlarmType,"烟感报警拉闸");
  1218. }
  1219. else if(relayCode == SW_TILT_ALARM)
  1220. {
  1221. strcpy(strAlarmType,"倾斜报警拉闸");
  1222. }
  1223. else if(relayCode == SW_LOCK_ALARM)
  1224. {
  1225. strcpy(strAlarmType,"锁具报警拉闸");
  1226. }
  1227. else if(relayCode == SW_LINE_TEMPERATURE_ALARM)
  1228. {
  1229. strcpy(strAlarmType,"线温报警拉闸");
  1230. }
  1231. else if(relayCode == SW_OVERVOLTAGE)
  1232. {
  1233. strcpy(strAlarmType,"过压报警拉闸");
  1234. }
  1235. else if(relayCode == SW_UNDERVOLTAGE)
  1236. {
  1237. strcpy(strAlarmType,"欠压报警拉闸");
  1238. }
  1239. else if(relayCode == SW_OVERLOAD_ALARM)
  1240. {
  1241. strcpy(strAlarmType,"过载报警拉闸");
  1242. }
  1243. else if(relayCode == SW_ELECTRIC_EXCESS)
  1244. {
  1245. strcpy(strAlarmType,"用电超额报警拉闸");
  1246. }
  1247. else if(relayCode == SW_OVER_SWITCH_OUT_COUNT)
  1248. {
  1249. strcpy(strAlarmType,"超自动合闸次数报警拉闸");
  1250. }
  1251. else if(relayCode == SW_FAST_CURRENT)
  1252. {
  1253. strcpy(strAlarmType,"快速电流报警拉闸");
  1254. }
  1255. else
  1256. {
  1257. debug("无法识别报警!");
  1258. return 1;
  1259. }
  1260. //格式化报警内容
  1261. sprintf(strAlarm,"%s,%s,时间:%s \n",strName,strAlarmType,GetCurrentTime());
  1262. log(strAlarm);
  1263. //更新到报警故障表
  1264. sprintf(updateSql,"update dev_fault set fault_details = '%s',fault_state = 1,fault_time = now() where "
  1265. "device_mac = '%s' and device_mac_node = '%s' and relay_code = %d",strAlarm,mac,subMac,relayCode);
  1266. excuteSql(_db,updateSql);
  1267. affectedRows = mysql_affected_rows(_db);
  1268. if (affectedRows < 1)
  1269. {
  1270. sprintf(insertSql,"insert into dev_fault(device_mac,device_mac_node,fault_details,relay_code,fault_state,fault_time)values('%s','%s','%s',%d,1,now())",
  1271. mac,subMac,strAlarm,relayCode);
  1272. excuteSql(_db,insertSql);
  1273. }
  1274. return 0;
  1275. }
  1276. //比较两个时间字符串的大小
  1277. int compareTimes(const char *time1, const char *time2)
  1278. {
  1279. struct tm tm_base, tm_time1, tm_time2;
  1280. // 设置基准日期为当前日期
  1281. time_t current_time = time(NULL);
  1282. localtime_r(&current_time, &tm_base);
  1283. // 解析时间字符串1
  1284. if (strptime(time1, "%H:%M", &tm_time1) == NULL)
  1285. {
  1286. fprintf(stderr, "Failed to parse time1\n");
  1287. return 0; // or handle the error in an appropriate way
  1288. }
  1289. // 解析时间字符串2
  1290. if (strptime(time2, "%H:%M", &tm_time2) == NULL)
  1291. {
  1292. fprintf(stderr, "Failed to parse time2\n");
  1293. return 0; // or handle the error in an appropriate way
  1294. }
  1295. // 设置日期部分为基准日期的日期部分
  1296. tm_time1.tm_year = tm_base.tm_year;
  1297. tm_time1.tm_mon = tm_base.tm_mon;
  1298. tm_time1.tm_mday = tm_base.tm_mday;
  1299. tm_time2.tm_year = tm_base.tm_year;
  1300. tm_time2.tm_mon = tm_base.tm_mon;
  1301. tm_time2.tm_mday = tm_base.tm_mday;
  1302. // 将 struct tm 结构转换为 time_t 类型
  1303. time_t t1 = mktime(&tm_time1);
  1304. time_t t2 = mktime(&tm_time2);
  1305. // 检查转换是否成功
  1306. if (t1 == -1 || t2 == -1)
  1307. {
  1308. fprintf(stderr, "Failed to convert time to time_t\n");
  1309. return 0; // or handle the error in an appropriate way
  1310. }
  1311. // 比较时间并返回相应的结果
  1312. if (t1 < t2)
  1313. {
  1314. return -1;
  1315. } else if (t1 > t2)
  1316. {
  1317. return 1;
  1318. } else
  1319. {
  1320. return 0;
  1321. }
  1322. }
  1323. //比较两个时间结构体的的大小
  1324. int compareModifiedTimes(struct tm t1, struct tm t2)
  1325. {
  1326. // 将时间结构体转换为秒数
  1327. time_t time1 = mktime(&t1);
  1328. time_t time2 = mktime(&t2);
  1329. // 比较秒数
  1330. if (time1 < time2) {
  1331. return -1;
  1332. } else if (time1 > time2) {
  1333. return 1;
  1334. } else {
  1335. return 0;
  1336. }
  1337. }
  1338. //比较给定时间和系统当前时间的函数
  1339. int compareWithCurrentTime(struct tm t1)
  1340. {
  1341. // 获取系统当前时间
  1342. time_t currentTime;
  1343. time(&currentTime);
  1344. // 将给定时间结构体转换为秒数
  1345. time_t givenTime = mktime(&t1);
  1346. // 比较秒数
  1347. if (givenTime < currentTime) {
  1348. return -1;
  1349. } else if (givenTime > currentTime) {
  1350. return 1;
  1351. } else {
  1352. return 0;
  1353. }
  1354. }
  1355. //将需要处理sql放入队列
  1356. void* sendtoqueue(ArrQueue *pQueue,char* stringSql)
  1357. {
  1358. ElemType *elememt = (ElemType *)malloc(sizeof(ElemType));
  1359. if(elememt==NULL)
  1360. {
  1361. printf("0 malloc(sizeof(ElemType)) \n");
  1362. exit(0);
  1363. }
  1364. memset(elememt,0,sizeof(ElemType));
  1365. if(strlen(stringSql)>1024)
  1366. {
  1367. printf("stringSql length is too long \n");
  1368. exit(0);
  1369. }
  1370. elememt->len = strlen(stringSql);
  1371. strcpy(elememt->buf,stringSql);
  1372. EnQueue(pQueue,elememt);
  1373. return NULL;
  1374. }
  1375. //循环从队列中取出数据处理
  1376. void* getqueue(void *data)
  1377. {
  1378. MYSQL *_db = NULL;
  1379. ElemType *elememt;
  1380. if (!_db)
  1381. {
  1382. // 先申请内存再初始化
  1383. _db = malloc(sizeof(MYSQL));
  1384. db_init(_db);
  1385. }
  1386. struct my_thread_info *info = data;
  1387. while(1)
  1388. {
  1389. usleep(1000*1);
  1390. DeQueue(m_pque,&elememt);
  1391. if(elememt == NULL)
  1392. {
  1393. printf("elememt == NULL,number:%d\n",info->which);
  1394. continue;
  1395. }
  1396. excuteSql(_db,elememt->buf);
  1397. free(elememt);
  1398. //log("getqueue sql number:%d \n",info->which);
  1399. }
  1400. free(info);
  1401. return NULL;
  1402. }
  1403. //创建任务线程处理数据库执行
  1404. void CreateDbHandThread(void)
  1405. {
  1406. int rc;
  1407. long t;
  1408. struct my_thread_info *info;
  1409. sleep(1);
  1410. for (t = 0; t < NUM_THREADS_UPLOAD_g; t++)
  1411. {
  1412. info = malloc(sizeof(struct my_thread_info));
  1413. info->which = t;
  1414. rc = pthread_create(&threads[t], NULL, getqueue, info);
  1415. if (rc)
  1416. {
  1417. printf("ERROR; return code from pthread_create() is %d\n", rc);
  1418. exit(-1);
  1419. }
  1420. printf("pthread_create() threadid:%lu is started \n",threads[t]);
  1421. sleep(1);
  1422. }
  1423. // for (t = 0; t < NUM_THREADS; t++)
  1424. // {
  1425. // pthread_join(threads[t], NULL);
  1426. // }
  1427. }
  1428. //打印队列状态,队列处理线程状态,10min打印一次
  1429. int PrintQueueThreadState(void)
  1430. {
  1431. if(timeGloble_g%600 == 0 && NUM_THREADS_UPLOAD_g>0)
  1432. {
  1433. int i = 0;
  1434. char strState[256] = {0};
  1435. int pthread_kill_err;
  1436. memset(strState,0x0,256);
  1437. sprintf(strState,"pid:%d,队列大小:%d",getpid(),GetLength(m_pque));
  1438. for(i=0;i<NUM_THREADS_UPLOAD_g;i++)
  1439. {
  1440. pthread_kill_err = pthread_kill(threads[i],0);
  1441. sprintf(strState,"%s,tid:%lu(%s)",strState,threads[i],(pthread_kill_err==0)?"alive":"death");
  1442. }
  1443. log("%s \n",strState);
  1444. }
  1445. return 0;
  1446. }
  1447. //关于远程升级
  1448. //生成CRC查询表
  1449. void init_crc32_tab(void)
  1450. {
  1451. int32_t i, j;
  1452. uint32_t crc;
  1453. if (have_table)
  1454. {
  1455. return;
  1456. }
  1457. have_table = 1;
  1458. for(i = 0; i < 256; i++)
  1459. {
  1460. crc = (uint32_t )i;
  1461. for(j = 0; j < 8; j++)
  1462. {
  1463. if(crc & 0X00000001L)
  1464. {
  1465. crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
  1466. }
  1467. else
  1468. {
  1469. crc = crc >> 1;
  1470. }
  1471. }
  1472. crc_table32[i] = crc;
  1473. }
  1474. }
  1475. //获得CRC
  1476. uint32_t get_crc32(uint32_t crcinit, uint8_t *bs, uint32_t bssize)
  1477. {
  1478. uint32_t crc = crcinit ^ 0XFFFFFFFF;
  1479. while(bssize--)
  1480. {
  1481. crc = (crc>>8)^crc_table32[(crc&0XFF)^*bs++];
  1482. }
  1483. return crc ^ 0XFFFFFFFF;
  1484. }
  1485. //根据mac查询对应升级文件名
  1486. char* GetFileNameByMac(list_node* u_list,char* mac)
  1487. {
  1488. list_node* list = u_list;
  1489. if(list == NULL) return NULL;
  1490. while(list)
  1491. {
  1492. upgrade_user_info* info = (upgrade_user_info*)list->data;
  1493. if(strcmp(info->mac,mac) == 0)
  1494. {
  1495. return info->ota_file_name;
  1496. }
  1497. list = list->next;
  1498. }
  1499. return NULL;
  1500. }
  1501. //根据文件名和包序号查询分包数据
  1502. ota_info* GetOtaInfoByFileName(list_node* f_list,char* filename)
  1503. {
  1504. list_node* list = f_list;
  1505. if(list == NULL) return NULL;
  1506. while(list)
  1507. {
  1508. ota_info* info = (ota_info*)list->data;
  1509. if(strcmp(info->new_file_name,filename) == 0)
  1510. {
  1511. return info;
  1512. }
  1513. list = list->next;
  1514. }
  1515. return NULL;
  1516. }
  1517. /******************************************************************
  1518. * Function Name: UpgradeFileAddFromDB
  1519. * Arguments:
  1520. * Return Value: void
  1521. * Date: 2022-04-02
  1522. * Editor: chw
  1523. * Description: 新增升级文件映射节点
  1524. ******************************************************************/
  1525. void UpgradeFileAddFromDB(list_node* f_list,char* filename,MYSQL *_db,int ota_mode)
  1526. {
  1527. char logstr[512] = {0};
  1528. unsigned short ota_file_total_packets = 0;
  1529. unsigned int file_length_bytes = 0;
  1530. unsigned int ota_length_bytes = 0;
  1531. list_node* list = f_list;
  1532. ota_info* info = (ota_info*)malloc(sizeof(ota_info));
  1533. memset(info,0x0,sizeof(ota_info));
  1534. ota_info* s = GetOtaInfoByFileName(file_list,filename);
  1535. if(s != NULL)
  1536. {
  1537. log("有文件节点,不新增! \n");
  1538. free(info);
  1539. info = NULL;
  1540. return;
  1541. }
  1542. //读取数据库升级文件
  1543. unsigned char *fp = readfile_from_db(filename,_db,&file_length_bytes);
  1544. if (file_length_bytes <= 0)
  1545. {
  1546. log("%s file_length_bytes <= 0 ! \n",file_length_bytes);
  1547. free(info);
  1548. info = NULL;
  1549. return;
  1550. }
  1551. //计算数据库升级文件crc32校验
  1552. init_crc32_tab();
  1553. uint32_t crc_value = 0;
  1554. if(calc_crc32_from_buff(fp,file_length_bytes,&crc_value) == 0)
  1555. {
  1556. log("crc_value = %x\n",crc_value);
  1557. }
  1558. //全量
  1559. if(ota_mode == 1)
  1560. {
  1561. ota_length_bytes = file_length_bytes;
  1562. memcpy(info->buf,fp,file_length_bytes);
  1563. crc_value = get_crc32(0,info->buf,file_length_bytes);//ota文件crc校验
  1564. info->ota_mode = 1;//模式
  1565. strcpy(info->new_file_name,filename);//新文件名
  1566. info->new_file_len = file_length_bytes;//新文件长度
  1567. info->ota_file_len = file_length_bytes;//升级文件长度
  1568. info->new_file_crc = crc_value;//新文件crc32校验
  1569. info->ota_file_crc = info->new_file_crc;//升级文件crc32校验
  1570. ota_file_total_packets = file_length_bytes/ota_file_packet_len + 1;
  1571. info->ota_file_total_packets = ota_file_total_packets;//升级文件总包数
  1572. info->ota_file_packet_len = ota_file_packet_len;//升级文件每包数据长度
  1573. sprintf(logstr,"新文件名:%s,新文件长度:%d,升级文件长度:%d,升级文件总包数:%d,升级文件每包数据长度:%d,新文件crc32校验:%X,升级文件crc32校验:%X \n",
  1574. info->new_file_name,info->new_file_len,info->ota_file_len,info->ota_file_total_packets,info->ota_file_packet_len,info->new_file_crc,info->ota_file_crc);
  1575. log(logstr);
  1576. }
  1577. //差分
  1578. else
  1579. {
  1580. ota_length_bytes = file_length_bytes;
  1581. memcpy(info->buf,fp,ota_length_bytes);
  1582. crc_value = get_crc32(0,info->buf,ota_length_bytes);//ota文件crc校验
  1583. info->ota_mode = 0;//模式
  1584. memcpy(info->old_file_name,fp,48);//旧文件名
  1585. info->old_file_len = INT_FROM_BUFF(fp,48);//旧文件长度
  1586. info->old_file_crc = INT_FROM_BUFF(fp,52);//旧文件crc32 校验值
  1587. memcpy(info->new_file_name,fp+56,48);//新文件名
  1588. info->new_file_len = INT_FROM_BUFF(fp,104);//新文件的长度
  1589. info->new_file_crc = INT_FROM_BUFF(fp,108);//新文件crc32 校验值
  1590. info->ota_state = (char)0;//升级状态
  1591. info->ota_file_len = ota_length_bytes;//ota 文件的长度
  1592. info->ota_file_crc = crc_value;//ota 文件的crc32校验值
  1593. info->ota_file_total_packets = ota_length_bytes/ota_file_packet_len + 1;//ota文件的总的包数
  1594. info->ota_file_packet_len = ota_file_packet_len;//ota文件每包的数据长度
  1595. log("info->buf 模式:%d,旧文件名:%s,旧文件长度:%d,旧文件crc32:%X,新文件名:%s,新文件的长度:%d,新文件crc32:%X,ota状态:%d,ota文件的长度:%d,"
  1596. "ota文件的crc32:%X,ota文件的总的包数:%d,ota文件每包的数据长度:%d \n", info->ota_mode,info->old_file_name,info->old_file_len,
  1597. info->old_file_crc,info->new_file_name,info->new_file_len,info->new_file_crc,info->ota_state,info->ota_file_len,info->ota_file_crc,
  1598. info->ota_file_total_packets,info->ota_file_packet_len);
  1599. }
  1600. if(fp != NULL)
  1601. {
  1602. free(fp);
  1603. fp = NULL;
  1604. }
  1605. //第一个文件
  1606. if(list == NULL)
  1607. {
  1608. file_list = list_create((void*)info);
  1609. log("当前为文件映射第一个节点 \n");
  1610. }
  1611. //没有文件节点
  1612. else
  1613. {
  1614. list_insert_end(file_list,(void*)info);
  1615. log("没有文件节点,加入! \n");
  1616. }
  1617. return;
  1618. }
  1619. //数据库查询升级文件名
  1620. void GetUpgradeFileFromDB(char *mac,MYSQL *_db,char* filename)
  1621. {
  1622. MYSQL_RES* res = NULL;
  1623. MYSQL_ROW row;
  1624. char query[1024] = {0};
  1625. char ota_file[256] = {0};
  1626. int ota_mode = 0;
  1627. sprintf(query,"select file_name,ota_mode from dev_info_gateway where device_mac ='%s'",mac);
  1628. excuteSql(_db,query);
  1629. res = mysql_store_result(_db);
  1630. if (NULL == res)
  1631. {
  1632. return ;
  1633. }
  1634. row = mysql_fetch_row(res);
  1635. if (NULL == row)
  1636. {
  1637. mysql_free_result(res);
  1638. return ;
  1639. }
  1640. if(!row[0] || !row[1])
  1641. {
  1642. log("%s file_name、ota_mode为空 \n",mac);
  1643. mysql_free_result(res);
  1644. return ;
  1645. }
  1646. strcpy(ota_file,row[0]);
  1647. ota_mode = atoi(row[1]);
  1648. strcpy(filename,ota_file);
  1649. mysql_free_result(res);
  1650. //log("mac:%s,file_name:%s \n",mac,ota_file);
  1651. return ;
  1652. }
  1653. /******************************************************************
  1654. * Function Name: readfile_from_db
  1655. * Arguments:
  1656. * Return Value: void
  1657. * Date: 2022-04-29
  1658. * Editor: chw
  1659. * Description: 从数据库读取升级文件
  1660. ******************************************************************/
  1661. unsigned char *readfile_from_db(const char *filename, MYSQL *_db,int *file_length_bytes)
  1662. {
  1663. MYSQL_RES* res = NULL;
  1664. MYSQL_ROW row;
  1665. char sql[512] = {0};
  1666. int ret = 0;
  1667. unsigned long *lengths;
  1668. unsigned char* data;
  1669. MYSQL_BIND result;
  1670. MYSQL_STMT* stmt = mysql_stmt_init(_db);
  1671. assert(NULL!=stmt);
  1672. sprintf(sql,"select file_src from dev_upgrade_file where file_name ='%s'",filename);
  1673. ret = mysql_stmt_prepare(stmt, sql, strlen(sql));
  1674. assert(0==ret);
  1675. ret = mysql_stmt_execute(stmt);
  1676. assert(0==ret);
  1677. memset(&result,0x0,sizeof(result));
  1678. unsigned long total_length = 0;
  1679. result.buffer_type = MYSQL_TYPE_LONG_BLOB;
  1680. result.length = &total_length;
  1681. ret = mysql_stmt_bind_result(stmt, &result);
  1682. assert(0==ret);
  1683. ret = mysql_stmt_store_result(stmt);
  1684. assert(0==ret);
  1685. ret = mysql_stmt_fetch(stmt);
  1686. if(total_length <= 0)
  1687. {
  1688. log("total_length <= 0!\n");
  1689. mysql_stmt_close(stmt);
  1690. return NULL;
  1691. }
  1692. unsigned long start = 0;
  1693. //char buf[1024] = {0};
  1694. //lengths = mysql_fetch_lengths(stmt);
  1695. data = (unsigned char*)malloc(total_length);
  1696. *file_length_bytes = total_length;
  1697. if(data == NULL)
  1698. {
  1699. log("malloc data failed!");
  1700. return NULL;
  1701. }
  1702. log("readfile_from_db函数,total_length=%lu\n", total_length);
  1703. while (start<(int)total_length)
  1704. {
  1705. result.buffer = (data+start);
  1706. if(total_length < 1024)
  1707. {
  1708. result.buffer_length = total_length;
  1709. }
  1710. else if((start+1024) < total_length)
  1711. {
  1712. result.buffer_length = 1024;
  1713. }
  1714. else
  1715. {
  1716. result.buffer_length = total_length % 1024;
  1717. }
  1718. ret = mysql_stmt_fetch_column(stmt, &result, 0, start);
  1719. if (ret!=0)
  1720. {
  1721. log("code=%d, msg=%s", (int)mysql_errno(_db), mysql_error(_db));
  1722. free(data);
  1723. mysql_stmt_close(stmt);
  1724. return NULL;
  1725. }
  1726. start += result.buffer_length;
  1727. }
  1728. //log("%.*s\n", total_length, data);
  1729. //free(data);
  1730. mysql_stmt_close(stmt);
  1731. return data;
  1732. }
  1733. /******************************************************************
  1734. * Function Name: 获取缓存中的crc32
  1735. * Arguments:
  1736. * Return Value: void
  1737. * Date: 2022-04-29
  1738. * Editor: chw
  1739. * Description: 获取缓存中的crc32
  1740. ******************************************************************/
  1741. int32_t calc_crc32_from_buff(const char *buff,int len, uint32_t *uiCrcValue)
  1742. {
  1743. const uint32_t size = 2*1024;
  1744. uint32_t crc = 0; // CRC初始值为0
  1745. int remain = len; //剩余未计算长度
  1746. int index = 0;
  1747. while(remain>0)
  1748. {
  1749. if(remain > size)
  1750. {
  1751. crc = get_crc32(crc, buff + index, size);
  1752. index += size;
  1753. remain = remain-size;
  1754. }
  1755. else
  1756. {
  1757. crc = get_crc32(crc, buff + index, remain);
  1758. index += remain;
  1759. remain = 0;
  1760. }
  1761. }
  1762. *uiCrcValue = crc;
  1763. return 0;
  1764. }
  1765. #ifdef UPGRADE_BY_FILE
  1766. //获取文件长度
  1767. int GetFileLength(char* file_path)
  1768. {
  1769. FILE* pFile = fopen(file_path,"r");
  1770. if(pFile == NULL)
  1771. {
  1772. return -1;
  1773. }
  1774. fseek(pFile,0,SEEK_END);
  1775. unsigned int file_length_bytes = ftell(pFile);
  1776. fclose(pFile);
  1777. pFile = NULL;
  1778. return file_length_bytes;
  1779. }
  1780. //获得文件CRC
  1781. int32_t calc_file_crc32(const char *pFileName, uint32_t *uiCrcValue)
  1782. {
  1783. if(!pFileName || !uiCrcValue)
  1784. {
  1785. log("bad parameter\n");
  1786. return -1;
  1787. }
  1788. if(access(pFileName, F_OK|R_OK)!=0)
  1789. {
  1790. log("file not exist or reading file has not permission\n");
  1791. return -1;
  1792. }
  1793. const uint32_t size = 2*1024;
  1794. uint8_t crcbuf[size];
  1795. uint32_t rdlen;
  1796. uint32_t crc = 0; // CRC初始值为0
  1797. FILE *fd = NULL;
  1798. if((fd = fopen(pFileName, "r"))==NULL)
  1799. {
  1800. log("to do crc 32 check, open file error\n");
  1801. return -1;
  1802. }
  1803. while((rdlen=fread(crcbuf, sizeof(uint8_t), size, fd))>0)
  1804. {
  1805. crc = get_crc32(crc, crcbuf, rdlen);
  1806. }
  1807. log("calc_file_crc32:%X \n",crc);
  1808. *uiCrcValue = crc;
  1809. fclose(fd);
  1810. return 0;
  1811. }
  1812. //读取文件
  1813. // unsigned char *read_myfile(const char *path, int *file_size)
  1814. // {
  1815. // if(!path||!file_size)
  1816. // {
  1817. // log("bad parameter\n");
  1818. // return NULL;
  1819. // }
  1820. // //access
  1821. // if(access(path, F_OK|R_OK))
  1822. // {
  1823. // log("access test file error\n");
  1824. // return NULL;
  1825. // }
  1826. // //read file
  1827. // struct stat calib_stat;
  1828. // int ret = stat(path, &calib_stat);
  1829. // if(ret!=0)
  1830. // {
  1831. // log("File error\n");
  1832. // return NULL;
  1833. // }
  1834. // FILE *fd = fopen(path, "r");
  1835. // if(NULL == fd)
  1836. // {
  1837. // log("Open test file error\n");
  1838. // return NULL;
  1839. // }
  1840. // unsigned char *buffer = malloc(calib_stat.st_size);
  1841. // if(!buffer)
  1842. // {
  1843. // log("malloc error\n");
  1844. // fclose(fd);
  1845. // return NULL;
  1846. // }
  1847. // memset(buffer, 0, calib_stat.st_size);
  1848. // int totalSize = 0, readed = 0;
  1849. // while((readed = fread(buffer + totalSize,1, 1024,fd)) > 0)
  1850. // {
  1851. // totalSize += readed;
  1852. // }
  1853. // *file_size = totalSize;
  1854. // fclose(fd);
  1855. // return buffer;
  1856. // }
  1857. // //增加用户
  1858. // void UpgradeUserAdd(list_node* u_list,char* mac,char* file_name)
  1859. // {
  1860. // list_node* list = u_list;
  1861. // upgrade_user_info* info = (upgrade_user_info*)malloc(sizeof(upgrade_user_info));
  1862. // strcpy(info->mac,mac);
  1863. // strcpy(info->ota_file_name,file_name);
  1864. // //第一个用户
  1865. // if(list == NULL)
  1866. // {
  1867. // user_list = list_create((void*)info);
  1868. // }
  1869. // else
  1870. // {
  1871. // //没查询到用户
  1872. // if(GetFileNameByMac(u_list,mac) == NULL)
  1873. // {
  1874. // list_insert_end(u_list,(void*)info);
  1875. // }
  1876. // //查询到用户,修改
  1877. // else
  1878. // {
  1879. // while(list)
  1880. // {
  1881. // upgrade_user_info* old_info = (upgrade_user_info*)list->data;
  1882. // if(strcmp(old_info->mac,mac) == 0)
  1883. // {
  1884. // list->data = (void*)info;
  1885. // free(old_info);
  1886. // old_info = NULL;
  1887. // break;
  1888. // }
  1889. // list = list->next;
  1890. // }
  1891. // }
  1892. // }
  1893. // return;
  1894. // }
  1895. // //新增升级文件映射节点
  1896. // void UpgradeFileAdd(list_node* f_list,char* filename,int ota_mode)
  1897. // {
  1898. // char file_path[256];
  1899. // char logstr[512];
  1900. // unsigned short ota_file_total_packets = 0;
  1901. // unsigned int file_length_bytes = 0;
  1902. // unsigned int ota_length_bytes = 0;
  1903. // list_node* list = f_list;
  1904. // ota_info* info = (ota_info*)malloc(sizeof(ota_info));
  1905. // memset(info,0x0,sizeof(ota_info));
  1906. // sprintf(file_path,"/home/cao/ota/%s",filename);
  1907. // //计算文件crc32校验
  1908. // init_crc32_tab();
  1909. // uint32_t crc_value = 0;
  1910. // if(calc_file_crc32(file_path, &crc_value) == 0)
  1911. // {
  1912. // log("file_path:%s,crc_value = %x\n", file_path,crc_value);
  1913. // }
  1914. // //读取文件
  1915. // unsigned char *fp = read_myfile(file_path,(int*)&file_length_bytes);
  1916. // if (file_length_bytes <= 0)
  1917. // {
  1918. // log("%s file_length_bytes <= 0 ! \n",file_path);
  1919. // free(info);
  1920. // info = NULL;
  1921. // return;
  1922. // }
  1923. // //全量
  1924. // if(ota_mode == 1)
  1925. // {
  1926. // ota_length_bytes = file_length_bytes;
  1927. // memcpy(info->buf,fp,file_length_bytes);
  1928. // crc_value = get_crc32(0,info->buf,file_length_bytes);//ota文件crc校验
  1929. // info->ota_mode = 1;//模式
  1930. // strcpy(info->new_file_name,filename);//新文件名
  1931. // info->new_file_len = file_length_bytes;//新文件长度
  1932. // info->ota_file_len = file_length_bytes;//升级文件长度
  1933. // info->new_file_crc = crc_value;//新文件crc32校验
  1934. // info->ota_file_crc = info->new_file_crc;//升级文件crc32校验
  1935. // ota_file_total_packets = file_length_bytes/ota_file_packet_len + 1;
  1936. // info->ota_file_total_packets = ota_file_total_packets;//升级文件总包数
  1937. // info->ota_file_packet_len = ota_file_packet_len;//升级文件每包数据长度
  1938. // sprintf(logstr,"新文件名:%s,新文件长度:%d,升级文件长度:%d,升级文件总包数:%d,升级文件每包数据长度:%d,新文件crc32校验:%X,升级文件crc32校验:%X \n",
  1939. // info->new_file_name,info->new_file_len,info->ota_file_len,info->ota_file_total_packets,info->ota_file_packet_len,info->new_file_crc,info->ota_file_crc);
  1940. // log(logstr);
  1941. // }
  1942. // //差分
  1943. // else
  1944. // {
  1945. // ota_length_bytes = file_length_bytes-130;
  1946. // memcpy(info->buf,fp+130,ota_length_bytes);
  1947. // //crc_value = get_crc32(0,info->buf,file_length_bytes-130);//ota文件crc校验
  1948. // info->ota_mode = 0;//模式
  1949. // memcpy(info->old_file_name,fp+1,48);//旧文件名
  1950. // info->old_file_len = INT_FROM_BUFF(fp,49);//旧文件长度
  1951. // info->old_file_crc = INT_FROM_BUFF(fp,53);//旧文件crc32 校验值
  1952. // memcpy(info->new_file_name,fp+58,48);//新文件名
  1953. // info->new_file_len = INT_FROM_BUFF(fp,105);//新文件的长度
  1954. // info->new_file_crc = INT_FROM_BUFF(fp,109);//新文件crc32 校验值
  1955. // info->ota_state = (char)*(fp+113);//ota 状态
  1956. // info->ota_file_len = INT_FROM_BUFF(fp,114);//ota 文件的长度
  1957. // info->ota_file_crc = INT_FROM_BUFF(fp,118);//ota 文件的crc32校验值
  1958. // info->ota_file_total_packets = SHORT_FROM_BUFF(fp,122);//ota文件的总的包数
  1959. // info->ota_file_packet_len = SHORT_FROM_BUFF(fp,124);//ota文件每包的数据长度
  1960. // info->boot_addr = INT_FROM_BUFF(fp,126);//app 程序的启动地址
  1961. // log("info->buf 模式:%d,旧文件名:%s,旧文件长度:%d,旧文件crc32:%X,新文件名:%s,新文件的长度:%d,新文件crc32:%X,ota状态:%d,ota文件的长度:%d,"
  1962. // "ota文件的crc32:%X,ota文件的总的包数:%d,ota文件每包的数据长度:%d,app程序的启动地址:%X \n", info->ota_mode,info->old_file_name,info->old_file_len,
  1963. // info->old_file_crc,info->new_file_name,info->new_file_len,info->new_file_crc,info->ota_state,info->ota_file_len,info->ota_file_crc,
  1964. // info->ota_file_total_packets,info->ota_file_packet_len,info->boot_addr);
  1965. // }
  1966. // //log("info->buf crc = %x ,file_length_bytes = %d,ota_length_bytes = %d \n", crc_value,file_length_bytes,ota_length_bytes);
  1967. // if(fp != NULL)
  1968. // {
  1969. // free(fp);
  1970. // }
  1971. // //第一个文件
  1972. // if(list == NULL)
  1973. // {
  1974. // file_list = list_create((void*)info);
  1975. // log("当前为文件映射第一个节点 \n");
  1976. // }
  1977. // else
  1978. // {
  1979. // ota_info* s = GetOtaInfoByFileName(file_list,filename);
  1980. // if(s == NULL)
  1981. // {
  1982. // list_insert_end(file_list,(void*)info);
  1983. // log("没有文件节点,加入! \n");
  1984. // }
  1985. // else
  1986. // {
  1987. // log("有文件节点,不新增! \n");
  1988. // }
  1989. // }
  1990. // return;
  1991. // }
  1992. #endif