core.c 70 KB

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