电调.go 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601
  1. // controllers/用户.go
  2. package controllers
  3. import (
  4. "Tech/common"
  5. "Tech/models"
  6. "bytes"
  7. "encoding/json"
  8. "fmt"
  9. "io"
  10. "net/http"
  11. "time"
  12. "github.com/beego/beego/v2/client/orm"
  13. beego "github.com/beego/beego/v2/server/web"
  14. )
  15. func init() {
  16. // // 启动后台协程定期更新电调模型数据
  17. // go func() {
  18. // // 初始化延迟1秒执行,避免系统启动时的资源竞争
  19. // time.Sleep(1 * time.Second)
  20. // // 定时每5秒获取一次数据
  21. // ticker := time.NewTicker(5 * time.Second)
  22. // defer ticker.Stop()
  23. // for {
  24. // select {
  25. // case <-ticker.C:
  26. // updateElectricalData()
  27. // }
  28. // }
  29. // }()
  30. }
  31. // // updateElectricalData 从电调服务获取数据并更新模型
  32. // func updateElectricalData() {
  33. // defer func() {
  34. // if r := recover(); r != nil {
  35. // fmt.Printf("更新电调数据时发生错误: %v\n", r)
  36. // }
  37. // }()
  38. // // 获取 ElectricModelManager 单例实例
  39. // manager := models.GetInstance()
  40. // // 获取模型列表副本,避免长时间持有锁
  41. // manager.Mutex.RLock()
  42. // modelsCopy := make(map[string]models.EViewMapModel)
  43. // for k, v := range manager.Models {
  44. // modelsCopy[k] = v
  45. // }
  46. // manager.Mutex.RUnlock()
  47. // // 如果 Models 为空,不进行任何处理
  48. // if len(modelsCopy) == 0 {
  49. // return
  50. // }
  51. // // 遍历已有模型并分别更新
  52. // for _, viewMapModel := range modelsCopy {
  53. // if len(viewMapModel.Models) > 0 && time.Since(viewMapModel.LastBatchUpdate) >= 5*time.Second {
  54. // // 获取第一个模型作为参考来构建请求参数
  55. // firstModel := viewMapModel.Models[0]
  56. // // 从配置获取电调服务地址
  57. // electricalIP, err := beego.AppConfig.String("ElectricalIP")
  58. // if err != nil {
  59. // fmt.Printf("读取电调服务IP配置失败: %v\n", err)
  60. // continue
  61. // }
  62. // electricalPort, err := beego.AppConfig.Int("ElectricalPort")
  63. // if err != nil {
  64. // fmt.Printf("读取电调服务端口配置失败: %v\n", err)
  65. // continue
  66. // }
  67. // // 构造电调服务地址
  68. // electricalAddr := fmt.Sprintf("http://%s:%d/ServerCtrl/AllEqpmtList", electricalIP, electricalPort)
  69. // // 准备请求数据
  70. // type RequestData struct {
  71. // LineID int `json:"lineID"`
  72. // StationID int `json:"StationID"`
  73. // ViewID int `json:"ViewID"`
  74. // }
  75. // reqData := RequestData{
  76. // LineID: firstModel.LineID,
  77. // // StationID: firstModel.StationID,
  78. // // ViewID: firstModel.ViewID,
  79. // }
  80. // // 将请求数据转换为JSON
  81. // reqBody, err := json.Marshal(reqData)
  82. // if err != nil {
  83. // fmt.Printf("构造请求数据失败: %v\n", err)
  84. // continue
  85. // }
  86. // // 发送POST请求获取数据
  87. // resp, err := http.Post(electricalAddr, "application/json", bytes.NewBuffer(reqBody))
  88. // if err != nil {
  89. // fmt.Printf("调用电调服务获取所有设备列表接口失败: %v\n", err)
  90. // continue
  91. // }
  92. // // 读取响应体
  93. // bodyBytes, err := io.ReadAll(resp.Body)
  94. // resp.Body.Close()
  95. // if err != nil {
  96. // fmt.Printf("读取电调服务响应失败: %v\n", err)
  97. // continue
  98. // }
  99. // // 检查响应状态
  100. // if resp.StatusCode != http.StatusOK {
  101. // fmt.Printf("电调服务返回异常状态码: %d,响应内容: %s\n", resp.StatusCode, string(bodyBytes))
  102. // continue
  103. // }
  104. // // 解析JSON响应
  105. // var result map[string]interface{}
  106. // if err := json.Unmarshal(bodyBytes, &result); err != nil {
  107. // fmt.Printf("解析电调服务响应失败: %v\n", err)
  108. // continue
  109. // }
  110. // // 检查是否有data字段
  111. // if data, exists := result["data"]; exists {
  112. // // 解析data中的设备列表并更新到模型管理器
  113. // var equipments []models.DiandiaoModel
  114. // if equipBytes, err := json.Marshal(data); err == nil {
  115. // if err := json.Unmarshal(equipBytes, &equipments); err == nil {
  116. // // 更新总包设备数据 (在更新时加锁)
  117. // manager.UpdateBatchData(equipments)
  118. // fmt.Printf("成功更新线路%d的电调模型数据\n", firstModel.LineID)
  119. // } else {
  120. // fmt.Printf("解析设备列表失败: %v\n", err)
  121. // }
  122. // }
  123. // }
  124. // }
  125. // }
  126. // }
  127. type EDispatchController struct {
  128. beego.Controller
  129. }
  130. // /courserun/eqpmtstatus 更新电调设备状态
  131. func (c *EDispatchController) Eqpmtvalue() {
  132. var req models.DiandiaoModel
  133. requestBody := c.Ctx.Input.RequestBody
  134. println("Request Body:", string(requestBody))
  135. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
  136. c.Ctx.Output.SetStatus(400)
  137. c.Data["json"] = map[string]interface{}{
  138. "code": 400,
  139. "msg": "请求参数格式错误: " + err.Error(),
  140. }
  141. c.ServeJSON()
  142. return
  143. }
  144. // 获取 ElectricModelManager 单例实例
  145. manager := models.GetInstance()
  146. // 更新单个设备数据
  147. manager.UpdateSingleDevice(req)
  148. c.Data["json"] = map[string]interface{}{
  149. "code": 200,
  150. "msg": "更新电调设备状态",
  151. }
  152. c.ServeJSON()
  153. }
  154. // /操作日志req
  155. type Addctrllog_req struct {
  156. CtrlType int `json:"CtrlType"`
  157. CtrlSubType int `json:"CtrlSubType"`
  158. CtrlFrom int `json:"CtrlFrom"`
  159. CtrlUser string `json:"CtrlUser"`
  160. Param1 string `json:"Param1"`
  161. Param2 string `json:"Param2"`
  162. Param3 string `json:"Param3"`
  163. Param4 string `json:"Param4"`
  164. Param5 string `json:"Param5"`
  165. }
  166. // 自动评价数据结构体
  167. type AutoEvaData struct {
  168. RunLogID int `orm:"column(运行记录编号)" json:"runLogID"`
  169. SeqNo int `orm:"column(序号)" json:"seqNo"`
  170. EvaName string `orm:"column(评价名称)" json:"evaName"`
  171. CourseID int `orm:"column(课程ID)" json:"courseID"`
  172. IsOperated int `orm:"column(是否操作)" json:"isOperated"`
  173. NodeID int `orm:"column(节点ID)" json:"nodeID"`
  174. EvaType int `orm:"column(评价类型)" json:"evaType"`
  175. TextParam1 string `orm:"column(文本参数1)" json:"textParam1"`
  176. TextParam2 string `orm:"column(文本参数2)" json:"textParam2"`
  177. TextParam3 string `orm:"column(文本参数3)" json:"textParam3"`
  178. TextParam4 string `orm:"column(文本参数4)" json:"textParam4"`
  179. TextParam5 string `orm:"column(文本参数5)" json:"textParam5"`
  180. }
  181. // 评价结果结构体
  182. type EvaResult struct {
  183. Code int `json:"code"` // 状态码:200-成功,400-失败
  184. Message string `json:"message"` // 描述信息
  185. EvaName string `json:"evaName"` // 评价名称
  186. IsOperated int `json:"isOperated"` // 是否操作:0-未操作,1-已操作
  187. OperScore float64 `json:"operScore"` // 操作得分
  188. CourseScore float64 `json:"courseScore"` // 课程总分
  189. SeqNo int `json:"seqNo"` // 序号
  190. }
  191. // /实现自动评价
  192. func (c *EDispatchController) DoAutoEva(req Addctrllog_req) EvaResult {
  193. // 获取数据库连接
  194. o := orm.NewOrm()
  195. // 查找当前正在运行的课程
  196. var runningCourse models.CourseRunLog
  197. err := o.QueryTable(new(models.CourseRunLog)).
  198. Filter("CourseTime", 0).
  199. OrderBy("-RunLogID").
  200. One(&runningCourse)
  201. if err != nil {
  202. // 如果没有找到正在运行的课程,返回错误结果
  203. return EvaResult{
  204. Code: 400,
  205. Message: "没有找到正在运行的课程",
  206. }
  207. }
  208. // 使用自定义SQL查询获取自动评价所需数据
  209. var autoEvaData []AutoEvaData
  210. sql := `SELECT a.运行记录编号, a.序号, a.评价名称, b.课程ID, a.是否操作, b.节点ID,
  211. a.评价类型, b.文本参数1, b.文本参数2, b.文本参数3, b.文本参数4, b.文本参数5
  212. FROM CourseEvaLog a JOIN CourseOperationNode b ON a.评价映射ID = b.节点ID
  213. WHERE a.运行记录编号 = ? AND a.评价类型 = 1 ORDER BY a.序号`
  214. _, err = o.Raw(sql, runningCourse.RunLogID).QueryRows(&autoEvaData)
  215. if err != nil {
  216. return EvaResult{
  217. Code: 400,
  218. Message: "查询评价数据失败: " + err.Error(),
  219. }
  220. }
  221. // 如果没有评价数据,返回提示信息
  222. if len(autoEvaData) == 0 {
  223. return EvaResult{
  224. Code: 200,
  225. Message: "当前课程没有评价数据",
  226. CourseScore: runningCourse.CourseScore,
  227. }
  228. }
  229. // 查找第一个未操作的记录
  230. var foundEvaData *AutoEvaData
  231. var firstSeqNo int = -1
  232. for _, evaData := range autoEvaData {
  233. if evaData.IsOperated == 0 {
  234. if firstSeqNo == -1 {
  235. firstSeqNo = evaData.SeqNo
  236. }
  237. // 检查当前操作的序号是否是第一个未操作的序号
  238. if evaData.SeqNo == firstSeqNo {
  239. foundEvaData = &evaData
  240. break
  241. }
  242. }
  243. }
  244. // 如果没有找到未操作的记录,返回已完成提示
  245. if foundEvaData == nil {
  246. return EvaResult{
  247. Code: 200,
  248. Message: "所有评价项已完成",
  249. CourseScore: runningCourse.CourseScore,
  250. }
  251. }
  252. // 检查参数1和参数2是否为空
  253. if req.Param1 == "" || req.Param2 == "" {
  254. return EvaResult{
  255. Code: 400,
  256. Message: "操作参数不能为空",
  257. EvaName: foundEvaData.EvaName,
  258. IsOperated: 0,
  259. OperScore: 0,
  260. CourseScore: runningCourse.CourseScore,
  261. SeqNo: foundEvaData.SeqNo,
  262. }
  263. }
  264. // 比较参数1和参数2
  265. if req.Param1 == foundEvaData.TextParam1 && req.Param2 == foundEvaData.TextParam2 {
  266. // 参数匹配,需要更新对应的CourseEvaLog记录
  267. var evaLog models.CourseEvaLog
  268. err = o.QueryTable(new(models.CourseEvaLog)).
  269. Filter("RunLogID", foundEvaData.RunLogID).
  270. Filter("SeqNo", foundEvaData.SeqNo).
  271. One(&evaLog)
  272. if err != nil {
  273. return EvaResult{
  274. Code: 400,
  275. Message: "查询评价记录失败: " + err.Error(),
  276. }
  277. }
  278. // 计算操作时间
  279. operTime := 0
  280. // 只有在课程未结束时才计算操作时间(暂停标记为-1表示课程结束)
  281. if runningCourse.PauseFlag != -1 {
  282. // 解析课程开始时间
  283. startTime, err := time.ParseInLocation("2006-01-02 15:04:05", runningCourse.RunDateTime, time.Local)
  284. if err != nil {
  285. return EvaResult{
  286. Code: 400,
  287. Message: "解析课程开始时间失败: " + err.Error(),
  288. }
  289. }
  290. operTime = int(time.Since(startTime).Seconds()) - runningCourse.PauseTotalTime
  291. // 确保操作时间不为负数
  292. if operTime < 0 {
  293. operTime = 0
  294. }
  295. }
  296. // 计算操作得分
  297. operScore := 0.0
  298. // 已操作,得分为评价赋分-评价失分
  299. operScore = float64(evaLog.EvaScore - evaLog.EvaDeduction)
  300. // 更新CourseEvaLog表中的是否操作字段、操作得分和操作时间
  301. _, err = o.Raw(`
  302. UPDATE CourseEvaLog
  303. SET 是否操作 = ?, 操作得分 = ?, 操作时间 = ?
  304. WHERE 运行记录编号 = ? AND 序号 = ?
  305. `, 1, operScore, operTime, foundEvaData.RunLogID, foundEvaData.SeqNo).Exec()
  306. if err != nil {
  307. return EvaResult{
  308. Code: 400,
  309. Message: "更新节点操作状态失败: " + err.Error(),
  310. }
  311. }
  312. // 重新计算整个课程的总得分
  313. var totalScore float64
  314. err = o.Raw(`
  315. SELECT COALESCE(SUM(操作得分), 0)
  316. FROM CourseEvaLog
  317. WHERE 运行记录编号 = ?
  318. `, foundEvaData.RunLogID).QueryRow(&totalScore)
  319. if err != nil {
  320. return EvaResult{
  321. Code: 400,
  322. Message: "计算总得分失败: " + err.Error(),
  323. }
  324. }
  325. // 更新课程运行日志中的总得分
  326. _, err = o.Raw(`
  327. UPDATE CourseRunLog
  328. SET 课程得分 = ?
  329. WHERE 运行记录编号 = ?
  330. `, totalScore, foundEvaData.RunLogID).Exec()
  331. if err != nil {
  332. return EvaResult{
  333. Code: 400,
  334. Message: "更新总得分失败: " + err.Error(),
  335. }
  336. }
  337. // 创建通知数据
  338. notificationData := map[string]interface{}{
  339. "type": "evaluation_update",
  340. "runLogID": foundEvaData.RunLogID,
  341. "seqNo": foundEvaData.SeqNo,
  342. "evaName": foundEvaData.EvaName,
  343. "isOperated": 1,
  344. "operScore": operScore,
  345. "courseScore": totalScore,
  346. "timestamp": time.Now().Format("2006-01-02 15:04:05"),
  347. }
  348. // 通过SSE广播评价更新消息
  349. common.GlobalSSEManager.BroadcastMessage("evaluation_update", notificationData)
  350. // 返回成功结果
  351. return EvaResult{
  352. Code: 200,
  353. Message: "评价成功",
  354. EvaName: foundEvaData.EvaName,
  355. IsOperated: 1,
  356. OperScore: operScore,
  357. CourseScore: totalScore,
  358. SeqNo: foundEvaData.SeqNo,
  359. }
  360. } else {
  361. // 参数不匹配
  362. return EvaResult{
  363. Code: 400,
  364. Message: "操作参数不匹配",
  365. EvaName: foundEvaData.EvaName,
  366. IsOperated: 0,
  367. OperScore: 0,
  368. CourseScore: runningCourse.CourseScore,
  369. SeqNo: foundEvaData.SeqNo,
  370. }
  371. }
  372. }
  373. // /courserun/add_ctrl_log 添加电调控制日志
  374. func (c *EDispatchController) Addctrllog() {
  375. var req Addctrllog_req
  376. requestBody := c.Ctx.Input.RequestBody
  377. println("Request Body:", string(requestBody))
  378. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
  379. c.Ctx.Output.SetStatus(400)
  380. c.Data["json"] = map[string]interface{}{
  381. "code": 400,
  382. "msg": "请求参数格式错误: " + err.Error(),
  383. }
  384. c.ServeJSON()
  385. return
  386. }
  387. // 调用自动评价函数并获取评价结果
  388. evaResult := c.DoAutoEva(req)
  389. // 获取数据库连接
  390. o := orm.NewOrm()
  391. // 查找当前正在运行的课程
  392. var runningCourse models.CourseRunLog
  393. err := o.QueryTable(new(models.CourseRunLog)).
  394. Filter("CourseTime", 0).
  395. OrderBy("-RunLogID").
  396. One(&runningCourse)
  397. if err != nil {
  398. c.Ctx.Output.SetStatus(400)
  399. c.Data["json"] = map[string]interface{}{
  400. "code": 400,
  401. "msg": "查找当前运行课程失败: " + err.Error(),
  402. }
  403. c.ServeJSON()
  404. return
  405. }
  406. // 查找当前运行课程中最大的RunOperID
  407. var maxOperLog models.CourseOperLog
  408. var runOperID int
  409. err = o.QueryTable(new(models.CourseOperLog)).
  410. Filter("RunLogID", runningCourse.RunLogID).
  411. OrderBy("-RunOperID").
  412. One(&maxOperLog)
  413. if err != nil && err != orm.ErrNoRows {
  414. c.Ctx.Output.SetStatus(500)
  415. c.Data["json"] = map[string]interface{}{
  416. "code": 500,
  417. "msg": "查询操作日志失败: " + err.Error(),
  418. }
  419. c.ServeJSON()
  420. return
  421. }
  422. if err == orm.ErrNoRows {
  423. // 如果没有找到记录,则从1开始
  424. runOperID = 1
  425. } else {
  426. // 找到记录,则取最大值加1
  427. runOperID = maxOperLog.RunOperID + 1
  428. }
  429. runDateTime, err := time.ParseInLocation("2006-01-02 15:04:05", runningCourse.RunDateTime, time.Local)
  430. if err != nil {
  431. c.Data["json"] = map[string]interface{}{
  432. "code": 500,
  433. "msg": "解析课程开始时间失败: " + err.Error(),
  434. "runStatus": 0,
  435. "data": nil,
  436. }
  437. c.ServeJSON()
  438. return
  439. }
  440. // 计算从课程开始到现在的秒数,减去暂停累计时间
  441. operTime := int(time.Since(runDateTime).Seconds()) - runningCourse.PauseTotalTime
  442. // 创建操作日志记录
  443. operLog := models.CourseOperLog{
  444. RunLogID: runningCourse.RunLogID,
  445. RunCourseID: runningCourse.RunCourseID,
  446. RunOperID: runOperID,
  447. OperName: req.CtrlUser,
  448. OperTime: operTime,
  449. OperScore: 0, // 默认分数为0
  450. OperParam1: req.Param1,
  451. OperParam2: req.Param2,
  452. OperParam3: req.Param3,
  453. OperParam4: req.Param4,
  454. OperParam5: req.Param5,
  455. }
  456. // 插入操作日志记录到数据库
  457. _, err = o.Insert(&operLog)
  458. if err != nil {
  459. c.Ctx.Output.SetStatus(500)
  460. c.Data["json"] = map[string]interface{}{
  461. "code": 500,
  462. "msg": "插入操作日志失败: " + err.Error(),
  463. }
  464. c.ServeJSON()
  465. return
  466. }
  467. // 返回包含评价结果的信息
  468. c.Data["json"] = map[string]interface{}{
  469. "code": evaResult.Code,
  470. "msg": "添加操作日志成功",
  471. "evaMessage": evaResult.Message,
  472. "evaName": evaResult.EvaName,
  473. "isOperated": evaResult.IsOperated,
  474. "operScore": evaResult.OperScore,
  475. "courseScore": evaResult.CourseScore,
  476. "seqNo": evaResult.SeqNo,
  477. }
  478. c.ServeJSON()
  479. }
  480. // /serverctrl/subsysstatus 获取电调设备状态
  481. func (c *EDispatchController) SubSysStatus() {
  482. // 从配置文件读取电调服务IP和端口
  483. electricalIP, err := beego.AppConfig.String("ElectricalIP")
  484. if err != nil {
  485. c.Data["json"] = map[string]interface{}{
  486. "code": 500,
  487. "msg": "读取电调服务IP配置失败: " + err.Error(),
  488. }
  489. c.ServeJSON()
  490. return
  491. }
  492. electricalPort, err := beego.AppConfig.Int("ElectricalPort")
  493. if err != nil {
  494. c.Data["json"] = map[string]interface{}{
  495. "code": 500,
  496. "msg": "读取电调服务端口配置失败: " + err.Error(),
  497. }
  498. c.ServeJSON()
  499. return
  500. }
  501. // 构造电调服务地址
  502. electricalAddr := fmt.Sprintf("http://%s:%d/ServerCtrl/SubSysStatus", electricalIP, electricalPort)
  503. // 构造请求体,使用空的JSON对象
  504. reqBody := "{}"
  505. // 创建带适当头部的请求
  506. req, err := http.NewRequest("POST", electricalAddr, bytes.NewBufferString(reqBody))
  507. if err != nil {
  508. c.Data["json"] = map[string]interface{}{
  509. "code": 500,
  510. "msg": "创建请求失败: " + err.Error(),
  511. }
  512. c.ServeJSON()
  513. return
  514. }
  515. // 设置Content-Type头部
  516. req.Header.Set("Content-Type", "application/json")
  517. // 创建HTTP客户端并发送请求
  518. client := &http.Client{}
  519. resp, err := client.Do(req)
  520. if err != nil {
  521. c.Data["json"] = map[string]interface{}{
  522. "code": 500,
  523. "msg": "调用电调服务获取子系统状态接口失败: " + err.Error(),
  524. }
  525. c.ServeJSON()
  526. return
  527. }
  528. defer resp.Body.Close()
  529. // 检查响应状态
  530. if resp.StatusCode != http.StatusOK {
  531. bodyBytes, _ := io.ReadAll(resp.Body)
  532. c.Data["json"] = map[string]interface{}{
  533. "code": 500,
  534. "msg": fmt.Sprintf("电调服务返回异常状态码: %d,响应内容: %s", resp.StatusCode, string(bodyBytes)),
  535. }
  536. c.ServeJSON()
  537. return
  538. }
  539. // 读取并解析响应体
  540. bodyBytes, err := io.ReadAll(resp.Body)
  541. if err != nil {
  542. c.Data["json"] = map[string]interface{}{
  543. "code": 500,
  544. "msg": "读取电调服务响应失败: " + err.Error(),
  545. }
  546. c.ServeJSON()
  547. return
  548. }
  549. // 尝试解析电调服务返回的JSON
  550. var result map[string]interface{}
  551. if err := json.Unmarshal(bodyBytes, &result); err != nil {
  552. // 如果解析失败,返回原始内容
  553. c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
  554. c.Ctx.Output.Body(bodyBytes)
  555. return
  556. }
  557. // 如果解析成功,直接返回JSON结果
  558. c.Data["json"] = result
  559. c.ServeJSON()
  560. }
  561. func (c *EDispatchController) UpdateTestStatus() {
  562. }
  563. // /serverCtrl/alleqpmtlist 获取所有设备列表
  564. func (c *EDispatchController) AllEqpmtList() {
  565. // 转换缓存数据为指定格式
  566. type EquipmentData struct {
  567. DataID string `json:"dataId"`
  568. DataName string `json:"dataName"`
  569. Value string `json:"value"`
  570. ID string `json:"id"`
  571. EqpmtTypeID int `json:"eqpmtTypeID"`
  572. }
  573. // 从配置文件读取电调服务IP和端口
  574. electricalIP, err := beego.AppConfig.String("ElectricalIP")
  575. if err != nil {
  576. c.Data["json"] = map[string]interface{}{
  577. "code": 500,
  578. "msg": "读取电调服务IP配置失败: " + err.Error(),
  579. }
  580. c.ServeJSON()
  581. return
  582. }
  583. electricalPort, err := beego.AppConfig.Int("ElectricalPort")
  584. if err != nil {
  585. c.Data["json"] = map[string]interface{}{
  586. "code": 500,
  587. "msg": "读取电调服务端口配置失败: " + err.Error(),
  588. }
  589. c.ServeJSON()
  590. return
  591. }
  592. // 获取全量数据更新间隔配置,默认10秒
  593. fullDataIntervalSeconds := 10
  594. if interval, err := beego.AppConfig.Int("EGetAllDataInterval"); err == nil {
  595. fullDataIntervalSeconds = interval
  596. }
  597. // 构造电调服务地址
  598. electricalAddr := fmt.Sprintf("http://%s:%d/ServerCtrl/AllEqpmtList", electricalIP, electricalPort)
  599. // 获取最新的课程运行记录以获取线路号
  600. o := orm.NewOrm()
  601. var latestCourse models.CourseRunLog
  602. err = o.QueryTable(new(models.CourseRunLog)).
  603. OrderBy("-RunLogID").
  604. One(&latestCourse)
  605. if err != nil && err != orm.ErrNoRows {
  606. c.Data["json"] = map[string]interface{}{
  607. "code": 500,
  608. "msg": "查询最新课程运行记录失败: " + err.Error(),
  609. }
  610. c.ServeJSON()
  611. return
  612. }
  613. // 如果没有找到运行记录,默认线路号为0
  614. lineID := 0
  615. if err != orm.ErrNoRows {
  616. // 根据运行课程ID查询课程信息以获取线路号
  617. var courseInfo models.CourseInfo
  618. err = o.QueryTable(new(models.CourseInfo)).
  619. Filter("CourseID", latestCourse.RunCourseID).
  620. One(&courseInfo)
  621. if err != nil && err != orm.ErrNoRows {
  622. c.Data["json"] = map[string]interface{}{
  623. "code": 500,
  624. "msg": "查询课程信息失败: " + err.Error(),
  625. }
  626. c.ServeJSON()
  627. return
  628. }
  629. if err != orm.ErrNoRows {
  630. lineID = courseInfo.LineNo
  631. }
  632. }
  633. // 使用客户端IP作为客户端标识
  634. clientID := c.Ctx.Input.IP()
  635. // 获取 ElectricModelManager 单例实例
  636. manager := models.GetInstance()
  637. // 注册客户端
  638. manager.RegisterClient(clientID)
  639. // 注意:不再在函数退出时注销客户端,而是由 ElectricModelManager 内部定期清理长时间未访问的客户端
  640. // 检查是否应该发送全量数据
  641. shouldSendFullData := manager.ShouldSendFullData(fullDataIntervalSeconds)
  642. // 准备请求数据
  643. type RequestData struct {
  644. LineID int `json:"lineID"`
  645. StationID int `json:"StationID"`
  646. ViewID int `json:"ViewID"`
  647. }
  648. reqData := RequestData{
  649. LineID: lineID,
  650. StationID: 0,
  651. ViewID: 0,
  652. }
  653. // 将请求数据转换为JSON
  654. reqBody, err := json.Marshal(reqData)
  655. if err != nil {
  656. c.Data["json"] = map[string]interface{}{
  657. "code": 500,
  658. "msg": "构造请求数据失败: " + err.Error(),
  659. }
  660. c.ServeJSON()
  661. return
  662. }
  663. // 调用电调服务获取所有设备列表接口,使用POST方法
  664. resp, err := http.Post(electricalAddr, "application/json", bytes.NewBuffer(reqBody))
  665. if err != nil {
  666. c.Data["json"] = map[string]interface{}{
  667. "code": 500,
  668. "msg": "调用电调服务获取所有设备列表接口失败: " + err.Error(),
  669. }
  670. c.ServeJSON()
  671. return
  672. }
  673. defer resp.Body.Close()
  674. // 检查响应状态
  675. if resp.StatusCode != http.StatusOK {
  676. bodyBytes, _ := io.ReadAll(resp.Body)
  677. c.Data["json"] = map[string]interface{}{
  678. "code": 500,
  679. "msg": fmt.Sprintf("电调服务返回异常状态码: %d,响应内容: %s", resp.StatusCode, string(bodyBytes)),
  680. }
  681. c.ServeJSON()
  682. return
  683. }
  684. // 读取并解析响应体
  685. bodyBytes, err := io.ReadAll(resp.Body)
  686. if err != nil {
  687. c.Data["json"] = map[string]interface{}{
  688. "code": 500,
  689. "msg": "读取电调服务响应失败: " + err.Error(),
  690. }
  691. c.ServeJSON()
  692. return
  693. }
  694. // 尝试解析JSON响应
  695. var result map[string]interface{}
  696. if err := json.Unmarshal(bodyBytes, &result); err != nil {
  697. // 如果不是JSON格式,作为字符串返回
  698. c.Data["json"] = map[string]interface{}{
  699. "code": 200,
  700. "msg": "获取所有设备列表失败",
  701. "data": string(bodyBytes),
  702. }
  703. } else {
  704. // 如果是JSON格式,检查是否有data字段
  705. if data, exists := result["data"]; exists {
  706. // 解析data中的设备列表并更新到模型管理器
  707. var equipments []models.DiandiaoModel
  708. if equipBytes, err := json.Marshal(data); err == nil {
  709. if err := json.Unmarshal(equipBytes, &equipments); err == nil {
  710. // 更新总包设备数据
  711. manager.UpdateBatchData(equipments)
  712. }
  713. }
  714. // 构建当前设备数据映射
  715. currentDataMapping := make(map[string]string)
  716. var equipmentsData []EquipmentData
  717. // isFirst := true
  718. for _, model := range equipments {
  719. equip := EquipmentData{
  720. DataID: model.EqpmtStrID,
  721. ID: model.EqpmtStrID,
  722. DataName: model.EqpmtStdName,
  723. EqpmtTypeID: model.EqpmtTypeID,
  724. }
  725. if model.CMDType == 0 { //设备状态
  726. equip.Value = fmt.Sprintf("%d", model.EqpmtStatus)
  727. } else if model.CMDType == 1 { //设备数据控制
  728. equip.Value = fmt.Sprintf("%d", model.FValue)
  729. }
  730. // if isFirst {
  731. // // 生成0到100之间的随机整数
  732. // equip.Value = fmt.Sprintf("%d", rand.Intn(101))
  733. // isFirst = false
  734. // }
  735. // 添加到当前数据映射
  736. currentDataMapping[model.EqpmtStrID] = equip.Value
  737. equipmentsData = append(equipmentsData, equip)
  738. }
  739. // 如果应该发送全量数据
  740. if shouldSendFullData {
  741. c.Data["json"] = equipmentsData
  742. manager.UpdateFullDataTimestamp()
  743. manager.UpdateClientData(clientID, currentDataMapping)
  744. } else {
  745. // 否则只返回变化的数据
  746. changedData := manager.CompareWithClientData(clientID, currentDataMapping)
  747. // 构建变化的设备数据列表
  748. var changedEquipmentsData []EquipmentData
  749. for _, equip := range equipmentsData {
  750. if _, changed := changedData[equip.ID]; changed {
  751. changedEquipmentsData = append(changedEquipmentsData, equip)
  752. }
  753. }
  754. // 确保不会返回nil,即使没有变化也返回空数组
  755. if changedEquipmentsData == nil {
  756. changedEquipmentsData = []EquipmentData{}
  757. }
  758. c.Data["json"] = changedEquipmentsData
  759. // 更新客户端数据记录
  760. manager.UpdateClientData(clientID, currentDataMapping)
  761. }
  762. } else {
  763. // 如果没有data字段,返回整个响应
  764. c.Data["json"] = map[string]interface{}{
  765. "code": 500,
  766. "msg": "获取所有设备列表失败",
  767. }
  768. }
  769. }
  770. c.ServeJSON()
  771. }
  772. // // /serverCtrl/alleqpmtlist2 获取所有设备列表 测试使用
  773. // func (c *EDispatchController) AllEqpmtList2() {
  774. // // 转换缓存数据为指定格式
  775. // type EquipmentData struct {
  776. // DataID string `json:"dataId"`
  777. // DataName string `json:"dataName"`
  778. // Value string `json:"value"`
  779. // ID string `json:"id"`
  780. // }
  781. // // 从配置文件读取电调服务IP和端口
  782. // electricalIP, err := beego.AppConfig.String("ElectricalIP")
  783. // if err != nil {
  784. // c.Data["json"] = map[string]interface{}{
  785. // "code": 500,
  786. // "msg": "读取电调服务IP配置失败: " + err.Error(),
  787. // }
  788. // c.ServeJSON()
  789. // return
  790. // }
  791. // electricalPort, err := beego.AppConfig.Int("ElectricalPort")
  792. // if err != nil {
  793. // c.Data["json"] = map[string]interface{}{
  794. // "code": 500,
  795. // "msg": "读取电调服务端口配置失败: " + err.Error(),
  796. // }
  797. // c.ServeJSON()
  798. // return
  799. // }
  800. // // 构造电调服务地址
  801. // electricalAddr := fmt.Sprintf("http://%s:%d/ServerCtrl/AllEqpmtList", electricalIP, electricalPort)
  802. // // 获取最新的课程运行记录以获取线路号
  803. // o := orm.NewOrm()
  804. // var latestCourse models.CourseRunLog
  805. // err = o.QueryTable(new(models.CourseRunLog)).
  806. // OrderBy("-RunLogID").
  807. // One(&latestCourse)
  808. // if err != nil && err != orm.ErrNoRows {
  809. // c.Data["json"] = map[string]interface{}{
  810. // "code": 500,
  811. // "msg": "查询最新课程运行记录失败: " + err.Error(),
  812. // }
  813. // c.ServeJSON()
  814. // return
  815. // }
  816. // // 如果没有找到运行记录,默认线路号为0
  817. // lineID := 0
  818. // if err != orm.ErrNoRows {
  819. // // 根据运行课程ID查询课程信息以获取线路号
  820. // var courseInfo models.CourseInfo
  821. // err = o.QueryTable(new(models.CourseInfo)).
  822. // Filter("CourseID", latestCourse.RunCourseID).
  823. // One(&courseInfo)
  824. // if err != nil && err != orm.ErrNoRows {
  825. // c.Data["json"] = map[string]interface{}{
  826. // "code": 500,
  827. // "msg": "查询课程信息失败: " + err.Error(),
  828. // }
  829. // c.ServeJSON()
  830. // return
  831. // }
  832. // if err != orm.ErrNoRows {
  833. // lineID = courseInfo.LineNo
  834. // }
  835. // }
  836. // // 生成请求key
  837. // model := models.DiandiaoModel{
  838. // LineID: lineID,
  839. // }
  840. // key := model.GenerateModelKey()
  841. // // 获取 ElectricModelManager 单例实例
  842. // manager := models.GetInstance()
  843. // // 检查缓存中是否存在对应key的数据,且最后更新时间在5秒内
  844. // if viewMapModel, exists := manager.GetModelByKey(key); exists {
  845. // // 检查最后总包更新时间是否在5秒内
  846. // if time.Since(viewMapModel.LastBatchUpdate) <= 5*time.Second || time.Since(viewMapModel.LastDeviceUpdate) <= 5*time.Second {
  847. // var equipmentsData []EquipmentData
  848. // for _, model := range viewMapModel.Models {
  849. // equip := EquipmentData{
  850. // DataID: model.EqpmtStrID,
  851. // ID: model.EqpmtStrID,
  852. // DataName: model.EqpmtStdName,
  853. // }
  854. // switch model.CMDType {
  855. // case 0: //设备状态
  856. // equip.Value = fmt.Sprintf("%d", model.EqpmtStatus)
  857. // case 1: //设备数据控制
  858. // equip.Value = fmt.Sprintf("%d", model.FValue)
  859. // }
  860. // equipmentsData = append(equipmentsData, equip)
  861. // }
  862. // c.Data["json"] = equipmentsData
  863. // // 使用缓存数据
  864. // // c.Data["json"] = map[string]interface{}{
  865. // // "code": 200,
  866. // // "msg": "获取所有设备列表成功(缓存)",
  867. // // "data": equipmentsData,
  868. // // }
  869. // c.ServeJSON()
  870. // return
  871. // }
  872. // }
  873. // // 准备请求数据
  874. // type RequestData struct {
  875. // LineID int `json:"lineID"`
  876. // StationID int `json:"StationID"`
  877. // ViewID int `json:"ViewID"`
  878. // }
  879. // reqData := RequestData{
  880. // LineID: lineID,
  881. // StationID: 0,
  882. // ViewID: 0,
  883. // }
  884. // // 将请求数据转换为JSON
  885. // reqBody, err := json.Marshal(reqData)
  886. // if err != nil {
  887. // c.Data["json"] = map[string]interface{}{
  888. // "code": 500,
  889. // "msg": "构造请求数据失败: " + err.Error(),
  890. // }
  891. // c.ServeJSON()
  892. // return
  893. // }
  894. // // 调用电调服务获取所有设备列表接口,使用POST方法
  895. // resp, err := http.Post(electricalAddr, "application/json", bytes.NewBuffer(reqBody))
  896. // if err != nil {
  897. // c.Data["json"] = map[string]interface{}{
  898. // "code": 500,
  899. // "msg": "调用电调服务获取所有设备列表接口失败: " + err.Error(),
  900. // }
  901. // c.ServeJSON()
  902. // return
  903. // }
  904. // defer resp.Body.Close()
  905. // // 检查响应状态
  906. // if resp.StatusCode != http.StatusOK {
  907. // bodyBytes, _ := io.ReadAll(resp.Body)
  908. // c.Data["json"] = map[string]interface{}{
  909. // "code": 500,
  910. // "msg": fmt.Sprintf("电调服务返回异常状态码: %d,响应内容: %s", resp.StatusCode, string(bodyBytes)),
  911. // }
  912. // c.ServeJSON()
  913. // return
  914. // }
  915. // // 读取并解析响应体
  916. // bodyBytes, err := io.ReadAll(resp.Body)
  917. // if err != nil {
  918. // c.Data["json"] = map[string]interface{}{
  919. // "code": 500,
  920. // "msg": "读取电调服务响应失败: " + err.Error(),
  921. // }
  922. // c.ServeJSON()
  923. // return
  924. // }
  925. // // 尝试解析JSON响应
  926. // var result map[string]interface{}
  927. // if err := json.Unmarshal(bodyBytes, &result); err != nil {
  928. // // 如果不是JSON格式,作为字符串返回
  929. // c.Data["json"] = map[string]interface{}{
  930. // "code": 200,
  931. // "msg": "获取所有设备列表成功",
  932. // "data": string(bodyBytes),
  933. // }
  934. // } else {
  935. // // 如果是JSON格式,检查是否有data字段
  936. // if data, exists := result["data"]; exists {
  937. // // 解析data中的设备列表并更新到模型管理器
  938. // var equipments []models.DiandiaoModel
  939. // if equipBytes, err := json.Marshal(data); err == nil {
  940. // if err := json.Unmarshal(equipBytes, &equipments); err == nil {
  941. // // 更新总包设备数据
  942. // manager.UpdateBatchData(equipments)
  943. // }
  944. // }
  945. // var equipmentsData []EquipmentData
  946. // for _, model := range equipments {
  947. // equip := EquipmentData{
  948. // DataID: model.EqpmtStrID,
  949. // ID: model.EqpmtStrID,
  950. // DataName: model.EqpmtStdName,
  951. // }
  952. // if model.CMDType == 0 { //设备状态
  953. // equip.Value = fmt.Sprintf("%d", model.EqpmtStatus)
  954. // } else if model.CMDType == 1 { //设备数据控制
  955. // equip.Value = fmt.Sprintf("%d", model.FValue)
  956. // }
  957. // equipmentsData = append(equipmentsData, equip)
  958. // }
  959. // c.Data["json"] = equipmentsData
  960. // // // 返回响应
  961. // // c.Data["json"] = map[string]interface{}{
  962. // // "code": 200,
  963. // // "msg": "获取所有设备列表成功",
  964. // // "data": equipmentsData,
  965. // // }
  966. // } else {
  967. // // 如果没有data字段,返回整个响应
  968. // c.Data["json"] = map[string]interface{}{
  969. // "code": 500,
  970. // "msg": "获取所有设备列表失败",
  971. // }
  972. // }
  973. // }
  974. // c.ServeJSON()
  975. // }
  976. // /serverctrl/seteqpmtoper 设置电调设备操作
  977. func (c *EDispatchController) Seteqpmtoper() {
  978. // 定义接收的请求数据结构
  979. var req struct {
  980. EqpmtStrID string `json:"EqpmtStrID"`
  981. LineID int `json:"LineID"`
  982. CMDType int `json:"CMDType"`
  983. EqpmtStatus int `json:"EqpmtStatus"`
  984. FValue int `json:"fValue"`
  985. }
  986. // 解析请求体中的JSON数据
  987. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
  988. c.Ctx.Output.SetStatus(400)
  989. c.Data["json"] = map[string]interface{}{
  990. "code": 400,
  991. "msg": "请求参数格式错误: " + err.Error(),
  992. }
  993. c.ServeJSON()
  994. return
  995. }
  996. // 如果LineID为0,则尝试获取最近一次运行课程的线路ID
  997. lineID := req.LineID
  998. if lineID == 0 {
  999. o := orm.NewOrm()
  1000. var lastCourse models.CourseRunLog
  1001. // 查询最后运行的课程
  1002. err := o.QueryTable(new(models.CourseRunLog)).
  1003. OrderBy("-RunLogID").
  1004. One(&lastCourse)
  1005. if err == nil {
  1006. // 找到最后一门课程,查询其对应的课程信息以获取线路号
  1007. var courseInfo models.CourseInfo
  1008. err = o.QueryTable(new(models.CourseInfo)).
  1009. Filter("CourseID", lastCourse.RunCourseID).
  1010. One(&courseInfo)
  1011. if err == nil {
  1012. lineID = courseInfo.LineNo
  1013. } else {
  1014. // 查询失败,使用默认值
  1015. lineID = 555
  1016. }
  1017. } else {
  1018. // 没有找到历史课程,使用默认值
  1019. lineID = 555
  1020. }
  1021. }
  1022. // 构造转发给电调服务器的请求数据
  1023. forwardReq := struct {
  1024. EqpmtStrID string `json:"EqpmtStrID"`
  1025. LineID int `json:"LineID"`
  1026. EqpmtStdName string `json:"EqpmtStdName"`
  1027. CMDType int `json:"CMDType"`
  1028. EqpmtStatus int `json:"EqpmtStatus"`
  1029. CtrlType int `json:"CtrlType"`
  1030. OpeMark int `json:"OpeMark"`
  1031. FValue int `json:"fValue"`
  1032. NValueType int `json:"nValueType"`
  1033. IsReset int `json:"IsReset"`
  1034. }{
  1035. EqpmtStrID: req.EqpmtStrID,
  1036. LineID: lineID,
  1037. EqpmtStdName: "", // 默认空值
  1038. CMDType: req.CMDType,
  1039. EqpmtStatus: req.EqpmtStatus,
  1040. CtrlType: 1, // 默认值
  1041. OpeMark: 0, // 默认值
  1042. FValue: req.FValue,
  1043. NValueType: 0, // 默认值
  1044. IsReset: 0, // 默认值
  1045. }
  1046. // 将构造好的请求数据序列化为JSON
  1047. forwardReqBody, err := json.Marshal(forwardReq)
  1048. if err != nil {
  1049. c.Data["json"] = map[string]interface{}{
  1050. "code": 500,
  1051. "msg": "构造转发请求数据失败: " + err.Error(),
  1052. }
  1053. c.ServeJSON()
  1054. return
  1055. }
  1056. // 从配置文件读取电调服务IP和端口
  1057. electricalIP, err := beego.AppConfig.String("ElectricalIP")
  1058. if err != nil {
  1059. c.Data["json"] = map[string]interface{}{
  1060. "code": 500,
  1061. "msg": "读取电调服务IP配置失败: " + err.Error(),
  1062. }
  1063. c.ServeJSON()
  1064. return
  1065. }
  1066. electricalPort, err := beego.AppConfig.Int("ElectricalPort")
  1067. if err != nil {
  1068. c.Data["json"] = map[string]interface{}{
  1069. "code": 500,
  1070. "msg": "读取电调服务端口配置失败: " + err.Error(),
  1071. }
  1072. c.ServeJSON()
  1073. return
  1074. }
  1075. // 构造电调服务地址
  1076. electricalAddr := fmt.Sprintf("http://%s:%d/ServerCtrl/SetEqpmtOper", electricalIP, electricalPort)
  1077. // 将请求数据转发到电调服务器
  1078. resp, err := http.Post(electricalAddr, "application/json", bytes.NewBuffer(forwardReqBody))
  1079. if err != nil {
  1080. c.Data["json"] = map[string]interface{}{
  1081. "code": 500,
  1082. "msg": "转发请求到电调服务器失败: " + err.Error(),
  1083. }
  1084. c.ServeJSON()
  1085. return
  1086. }
  1087. defer resp.Body.Close()
  1088. fmt.Println("Seteqpmtoper 发送 JSON:", string(forwardReqBody))
  1089. // 读取响应体以便打印,然后将其重新放回供后续处理
  1090. respBodyBytes, err := io.ReadAll(resp.Body)
  1091. if err != nil {
  1092. fmt.Printf("Seteqpmtoper: 读取响应用于打印失败: %v\n", err)
  1093. } else {
  1094. fmt.Println("Seteqpmtoper 接收 JSON:", string(respBodyBytes))
  1095. // 由于后续代码还会读取 resp.Body,这里把数据重新放回
  1096. resp.Body = io.NopCloser(bytes.NewBuffer(respBodyBytes))
  1097. }
  1098. // 读取响应体
  1099. bodyBytes, err := io.ReadAll(resp.Body)
  1100. if err != nil {
  1101. c.Data["json"] = map[string]interface{}{
  1102. "code": 500,
  1103. "msg": "读取电调服务响应失败: " + err.Error(),
  1104. }
  1105. c.ServeJSON()
  1106. return
  1107. }
  1108. // 检查响应状态
  1109. if resp.StatusCode != http.StatusOK {
  1110. c.Data["json"] = map[string]interface{}{
  1111. "code": resp.StatusCode,
  1112. "msg": fmt.Sprintf("电调服务返回异常状态码: %d,响应内容: %s", resp.StatusCode, string(bodyBytes)),
  1113. }
  1114. c.ServeJSON()
  1115. return
  1116. }
  1117. // 尝试解析响应为JSON
  1118. var result map[string]interface{}
  1119. if err := json.Unmarshal(bodyBytes, &result); err != nil {
  1120. // 如果不是JSON格式,原样返回
  1121. c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
  1122. c.Ctx.Output.Body(bodyBytes)
  1123. return
  1124. }
  1125. // 返回电调服务器的响应
  1126. c.Data["json"] = result
  1127. c.ServeJSON()
  1128. }
  1129. // /serverctrl/seteqpmtfault 设置设备故障
  1130. func (c *EDispatchController) Seteqpmtfault() {
  1131. // 定义接收的请求数据结构
  1132. var req struct {
  1133. EqpmtStrID string `json:"EqpmtStrID"`
  1134. LineID int `json:"LineID"`
  1135. EventType int `json:"EventType"`
  1136. EventId int `json:"EventId"`
  1137. }
  1138. // 解析请求体中的JSON数据
  1139. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
  1140. c.Ctx.Output.SetStatus(400)
  1141. c.Data["json"] = map[string]interface{}{
  1142. "code": 400,
  1143. "msg": "请求参数格式错误: " + err.Error(),
  1144. }
  1145. c.ServeJSON()
  1146. return
  1147. }
  1148. // 如果LineID为0,则尝试获取最近一次运行课程的线路ID
  1149. lineID := req.LineID
  1150. if lineID == 0 {
  1151. o := orm.NewOrm()
  1152. var lastCourse models.CourseRunLog
  1153. // 查询最后运行的课程
  1154. err := o.QueryTable(new(models.CourseRunLog)).
  1155. OrderBy("-RunLogID").
  1156. One(&lastCourse)
  1157. if err == nil {
  1158. // 找到最后一门课程,查询其对应的课程信息以获取线路号
  1159. var courseInfo models.CourseInfo
  1160. err = o.QueryTable(new(models.CourseInfo)).
  1161. Filter("CourseID", lastCourse.RunCourseID).
  1162. One(&courseInfo)
  1163. if err == nil {
  1164. lineID = courseInfo.LineNo
  1165. } else {
  1166. // 查询失败,使用默认值
  1167. lineID = 555
  1168. }
  1169. } else {
  1170. // 没有找到历史课程,使用默认值
  1171. lineID = 555
  1172. }
  1173. }
  1174. // 构造转发给电调服务器的请求数据
  1175. forwardReq := struct {
  1176. EqpmtStrID string `json:"EqpmtStrID"`
  1177. LineID int `json:"LineID"`
  1178. EventType int `json:"EventType"`
  1179. EventId int `json:"EventId"`
  1180. }{
  1181. EqpmtStrID: req.EqpmtStrID,
  1182. LineID: lineID,
  1183. EventType: req.EventType,
  1184. EventId: req.EventId,
  1185. }
  1186. // 将构造好的请求数据序列化为JSON
  1187. forwardReqBody, err := json.Marshal(forwardReq)
  1188. if err != nil {
  1189. c.Data["json"] = map[string]interface{}{
  1190. "code": 500,
  1191. "msg": "构造转发请求数据失败: " + err.Error(),
  1192. }
  1193. c.ServeJSON()
  1194. return
  1195. }
  1196. // 从配置文件读取电调服务IP和端口
  1197. electricalIP, err := beego.AppConfig.String("ElectricalIP")
  1198. if err != nil {
  1199. c.Data["json"] = map[string]interface{}{
  1200. "code": 500,
  1201. "msg": "读取电调服务IP配置失败: " + err.Error(),
  1202. }
  1203. c.ServeJSON()
  1204. return
  1205. }
  1206. electricalPort, err := beego.AppConfig.Int("ElectricalPort")
  1207. if err != nil {
  1208. c.Data["json"] = map[string]interface{}{
  1209. "code": 500,
  1210. "msg": "读取电调服务端口配置失败: " + err.Error(),
  1211. }
  1212. c.ServeJSON()
  1213. return
  1214. }
  1215. // 构造电调服务地址
  1216. electricalAddr := fmt.Sprintf("http://%s:%d/ServerCtrl/SetEqpmtFault", electricalIP, electricalPort)
  1217. // 将请求数据转发到电调服务器
  1218. resp, err := http.Post(electricalAddr, "application/json", bytes.NewBuffer(forwardReqBody))
  1219. if err != nil {
  1220. c.Data["json"] = map[string]interface{}{
  1221. "code": 500,
  1222. "msg": "转发请求到电调服务器失败: " + err.Error(),
  1223. }
  1224. c.ServeJSON()
  1225. return
  1226. }
  1227. defer resp.Body.Close()
  1228. // 读取响应体
  1229. bodyBytes, err := io.ReadAll(resp.Body)
  1230. if err != nil {
  1231. c.Data["json"] = map[string]interface{}{
  1232. "code": 500,
  1233. "msg": "读取电调服务响应失败: " + err.Error(),
  1234. }
  1235. c.ServeJSON()
  1236. return
  1237. }
  1238. // 检查响应状态
  1239. if resp.StatusCode != http.StatusOK {
  1240. c.Data["json"] = map[string]interface{}{
  1241. "code": resp.StatusCode,
  1242. "msg": fmt.Sprintf("电调服务返回异常状态码: %d,响应内容: %s", resp.StatusCode, string(bodyBytes)),
  1243. }
  1244. c.ServeJSON()
  1245. return
  1246. }
  1247. // 尝试解析响应为JSON
  1248. var result map[string]interface{}
  1249. if err := json.Unmarshal(bodyBytes, &result); err != nil {
  1250. // 如果不是JSON格式,原样返回
  1251. c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
  1252. c.Ctx.Output.Body(bodyBytes)
  1253. return
  1254. }
  1255. // 返回电调服务器的响应
  1256. c.Data["json"] = result
  1257. c.ServeJSON()
  1258. }
  1259. // /serverctrl/geteqpmtfault 获取设备故障
  1260. func (c *EDispatchController) GetEqpmtFault() {
  1261. // 从配置文件读取电调服务IP和端口
  1262. electricalIP, err := beego.AppConfig.String("ElectricalIP")
  1263. if err != nil {
  1264. c.Data["json"] = map[string]interface{}{
  1265. "code": 500,
  1266. "msg": "读取电调服务IP配置失败: " + err.Error(),
  1267. }
  1268. c.ServeJSON()
  1269. return
  1270. }
  1271. electricalPort, err := beego.AppConfig.Int("ElectricalPort")
  1272. if err != nil {
  1273. c.Data["json"] = map[string]interface{}{
  1274. "code": 500,
  1275. "msg": "读取电调服务端口配置失败: " + err.Error(),
  1276. }
  1277. c.ServeJSON()
  1278. return
  1279. }
  1280. // 构造电调服务地址
  1281. electricalAddr := fmt.Sprintf("http://%s:%d/ServerCtrl/GetEqpmtFault", electricalIP, electricalPort)
  1282. // 构造请求体,使用空的JSON对象
  1283. reqBody := "{}"
  1284. // 创建带适当头部的请求
  1285. req, err := http.NewRequest("POST", electricalAddr, bytes.NewBufferString(reqBody))
  1286. if err != nil {
  1287. c.Data["json"] = map[string]interface{}{
  1288. "code": 500,
  1289. "msg": "创建请求失败: " + err.Error(),
  1290. }
  1291. c.ServeJSON()
  1292. return
  1293. }
  1294. // 设置Content-Type头部
  1295. req.Header.Set("Content-Type", "application/json")
  1296. // 创建HTTP客户端并发送请求
  1297. client := &http.Client{}
  1298. resp, err := client.Do(req)
  1299. if err != nil {
  1300. c.Data["json"] = map[string]interface{}{
  1301. "code": 500,
  1302. "msg": "调用电调服务获取设备故障接口失败: " + err.Error(),
  1303. }
  1304. c.ServeJSON()
  1305. return
  1306. }
  1307. defer resp.Body.Close()
  1308. // 检查响应状态
  1309. if resp.StatusCode != http.StatusOK {
  1310. bodyBytes, _ := io.ReadAll(resp.Body)
  1311. c.Data["json"] = map[string]interface{}{
  1312. "code": 500,
  1313. "msg": fmt.Sprintf("电调服务返回异常状态码: %d,响应内容: %s", resp.StatusCode, string(bodyBytes)),
  1314. }
  1315. c.ServeJSON()
  1316. return
  1317. }
  1318. // 读取并解析响应体
  1319. bodyBytes, err := io.ReadAll(resp.Body)
  1320. if err != nil {
  1321. c.Data["json"] = map[string]interface{}{
  1322. "code": 500,
  1323. "msg": "读取电调服务响应失败: " + err.Error(),
  1324. }
  1325. c.ServeJSON()
  1326. return
  1327. }
  1328. // 解析电调服务器的响应
  1329. var serverResp map[string]interface{}
  1330. if err := json.Unmarshal(bodyBytes, &serverResp); err != nil {
  1331. c.Data["json"] = map[string]interface{}{
  1332. "code": 500,
  1333. "msg": "解析电调服务响应失败: " + err.Error(),
  1334. }
  1335. c.ServeJSON()
  1336. return
  1337. }
  1338. // 检查是否有data字段
  1339. data, exists := serverResp["data"]
  1340. if !exists {
  1341. c.Data["json"] = map[string]interface{}{
  1342. "code": 500,
  1343. "msg": "电调服务响应缺少data字段",
  1344. }
  1345. c.ServeJSON()
  1346. return
  1347. }
  1348. // 解析data字段
  1349. dataBytes, _ := json.Marshal(data)
  1350. var faultData []map[string]interface{}
  1351. if err := json.Unmarshal(dataBytes, &faultData); err != nil {
  1352. c.Data["json"] = map[string]interface{}{
  1353. "code": 500,
  1354. "msg": "解析故障数据失败: " + err.Error(),
  1355. }
  1356. c.ServeJSON()
  1357. return
  1358. }
  1359. // 转换为UI需要的格式
  1360. type UIFaultData struct {
  1361. SeqNo int `json:"SeqNo"`
  1362. EqpmtID string `json:"EqpmtID"`
  1363. EqpmtName string `json:"EqpmtName"`
  1364. FaultID int `json:"FaultID"`
  1365. FaultTime int `json:"FaultTime"`
  1366. EqpmtTypeID int `json:"EqpmtTypeID"`
  1367. }
  1368. var uiData []UIFaultData
  1369. seqNo := 1
  1370. for _, item := range faultData {
  1371. eqpmtID, _ := item["EqpmtID"].(string)
  1372. EqpmtTypeID, _ := item["EqpmtTypeID"].(int)
  1373. // 解析设备故障数组
  1374. eqpmtFault, ok := item["EqpmtFault"].([]interface{})
  1375. if !ok || len(eqpmtFault) == 0 {
  1376. continue
  1377. }
  1378. // 取第一个故障记录
  1379. faultMap, ok := eqpmtFault[0].(map[string]interface{})
  1380. if !ok {
  1381. continue
  1382. }
  1383. faultID, _ := faultMap["FaultID"].(float64) // JSON数字默认解析为float64
  1384. // 解析故障时间并计算相对于当前时间的秒数
  1385. faultTimeStr, _ := faultMap["FaultTime"].(string)
  1386. faultTime, err := time.ParseInLocation("2006-01-02 15:04:05", faultTimeStr, time.Local)
  1387. if err != nil {
  1388. fmt.Printf("解析故障时间失败: %v\n", err)
  1389. continue
  1390. }
  1391. // 计算距离现在多少秒
  1392. secondsAgo := int(time.Since(faultTime).Seconds())
  1393. uiFault := UIFaultData{
  1394. SeqNo: seqNo,
  1395. EqpmtID: eqpmtID,
  1396. EqpmtName: "", // 原始数据中未提供设备名称,留空
  1397. FaultID: int(faultID),
  1398. FaultTime: secondsAgo,
  1399. EqpmtTypeID: int(EqpmtTypeID),
  1400. }
  1401. uiData = append(uiData, uiFault)
  1402. seqNo++
  1403. }
  1404. // 构造返回给UI的数据
  1405. result := map[string]interface{}{
  1406. "code": 200,
  1407. "data": uiData,
  1408. "msg": serverResp["msg"],
  1409. }
  1410. c.Data["json"] = result
  1411. c.ServeJSON()
  1412. }