core.c 70 KB

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