restful.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. package gb28181
  2. import (
  3. "fmt"
  4. "net/http"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "m7s.live/engine/v4/util"
  9. )
  10. var (
  11. playScaleValues = map[float32]bool{0.25: true, 0.5: true, 1: true, 2: true, 4: true}
  12. )
  13. func (c *GB28181Config) API_list(w http.ResponseWriter, r *http.Request) {
  14. query := r.URL.Query()
  15. if query.Get("interval") == "" {
  16. query.Set("interval", "5s")
  17. }
  18. util.ReturnFetchValue(func() (list []*Device) {
  19. list = make([]*Device, 0)
  20. Devices.Range(func(key, value interface{}) bool {
  21. list = append(list, value.(*Device))
  22. return true
  23. })
  24. return
  25. }, w, r)
  26. }
  27. func (c *GB28181Config) API_records(w http.ResponseWriter, r *http.Request) {
  28. query := r.URL.Query()
  29. id := query.Get("id")
  30. channel := query.Get("channel")
  31. startTime := query.Get("startTime")
  32. endTime := query.Get("endTime")
  33. trange := strings.Split(query.Get("range"), "-")
  34. if len(trange) == 2 {
  35. startTime = trange[0]
  36. endTime = trange[1]
  37. }
  38. if c := FindChannel(id, channel); c != nil {
  39. res, err := c.QueryRecord(startTime, endTime)
  40. if err == nil {
  41. util.ReturnValue(res, w, r)
  42. } else {
  43. util.ReturnError(util.APIErrorInternal, err.Error(), w, r)
  44. }
  45. } else {
  46. util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
  47. }
  48. }
  49. func (c *GB28181Config) API_control(w http.ResponseWriter, r *http.Request) {
  50. id := r.URL.Query().Get("id")
  51. channel := r.URL.Query().Get("channel")
  52. ptzcmd := r.URL.Query().Get("ptzcmd")
  53. if c := FindChannel(id, channel); c != nil {
  54. util.ReturnError(0, fmt.Sprintf("control code:%d", c.Control(ptzcmd)), w, r)
  55. } else {
  56. util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
  57. }
  58. }
  59. func (c *GB28181Config) API_ptz(w http.ResponseWriter, r *http.Request) {
  60. q := r.URL.Query()
  61. id := q.Get("id")
  62. channel := q.Get("channel")
  63. cmd := q.Get("cmd") // 命令名称,见 ptz.go name2code 定义
  64. hs := q.Get("hSpeed") // 水平速度
  65. vs := q.Get("vSpeed") // 垂直速度
  66. zs := q.Get("zSpeed") // 缩放速度
  67. hsN, err := strconv.ParseUint(hs, 10, 8)
  68. if err != nil {
  69. util.ReturnError(util.APIErrorQueryParse, "hSpeed parameter is invalid", w, r)
  70. return
  71. }
  72. vsN, err := strconv.ParseUint(vs, 10, 8)
  73. if err != nil {
  74. util.ReturnError(util.APIErrorQueryParse, "vSpeed parameter is invalid", w, r)
  75. return
  76. }
  77. zsN, err := strconv.ParseUint(zs, 10, 8)
  78. if err != nil {
  79. util.ReturnError(util.APIErrorQueryParse, "zSpeed parameter is invalid", w, r)
  80. return
  81. }
  82. ptzcmd, err := toPtzStrByCmdName(cmd, uint8(hsN), uint8(vsN), uint8(zsN))
  83. if err != nil {
  84. util.ReturnError(util.APIErrorQueryParse, err.Error(), w, r)
  85. return
  86. }
  87. if c := FindChannel(id, channel); c != nil {
  88. code := c.Control(ptzcmd)
  89. util.ReturnError(code, "device received", w, r)
  90. } else {
  91. util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
  92. }
  93. }
  94. func (c *GB28181Config) API_invite(w http.ResponseWriter, r *http.Request) {
  95. query := r.URL.Query()
  96. id := query.Get("id")
  97. channel := query.Get("channel")
  98. streamPath := query.Get("streamPath")
  99. port, _ := strconv.Atoi(query.Get("mediaPort"))
  100. opt := InviteOptions{
  101. dump: query.Get("dump"),
  102. MediaPort: uint16(port),
  103. StreamPath: streamPath,
  104. }
  105. startTime := query.Get("startTime")
  106. endTime := query.Get("endTime")
  107. trange := strings.Split(query.Get("range"), "-")
  108. if len(trange) == 2 {
  109. startTime = trange[0]
  110. endTime = trange[1]
  111. }
  112. opt.Validate(startTime, endTime)
  113. if c := FindChannel(id, channel); c == nil {
  114. util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
  115. } else if opt.IsLive() && c.State.Load() > 0 {
  116. util.ReturnError(util.APIErrorQueryParse, "live stream already exists", w, r)
  117. } else if code, err := c.Invite(&opt); err == nil {
  118. // 删除缓存中的信息
  119. DeviceRecordState.Delete(c.DeviceID)
  120. if code == 200 {
  121. util.ReturnOK(w, r)
  122. } else {
  123. util.ReturnError(util.APIErrorInternal, fmt.Sprintf("invite return code %d", code), w, r)
  124. }
  125. } else {
  126. util.ReturnError(util.APIErrorInternal, err.Error(), w, r)
  127. }
  128. }
  129. func (c *GB28181Config) API_bye(w http.ResponseWriter, r *http.Request) {
  130. id := r.URL.Query().Get("id")
  131. channel := r.URL.Query().Get("channel")
  132. streamPath := r.URL.Query().Get("streamPath")
  133. if c := FindChannel(id, channel); c != nil {
  134. // 删除缓存中的信息
  135. DeviceRecordState.Delete(c.DeviceID)
  136. util.ReturnError(0, fmt.Sprintf("bye code:%d", c.Bye(streamPath)), w, r)
  137. } else {
  138. util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
  139. }
  140. }
  141. func (c *GB28181Config) API_play_pause(w http.ResponseWriter, r *http.Request) {
  142. id := r.URL.Query().Get("id")
  143. channel := r.URL.Query().Get("channel")
  144. streamPath := r.URL.Query().Get("streamPath")
  145. if c := FindChannel(id, channel); c != nil {
  146. util.ReturnError(0, fmt.Sprintf("pause code:%d", c.Pause(streamPath)), w, r)
  147. } else {
  148. util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
  149. }
  150. }
  151. func (c *GB28181Config) API_play_resume(w http.ResponseWriter, r *http.Request) {
  152. id := r.URL.Query().Get("id")
  153. channel := r.URL.Query().Get("channel")
  154. streamPath := r.URL.Query().Get("streamPath")
  155. if c := FindChannel(id, channel); c != nil {
  156. util.ReturnError(0, fmt.Sprintf("resume code:%d", c.Resume(streamPath)), w, r)
  157. } else {
  158. util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
  159. }
  160. }
  161. func (c *GB28181Config) API_play_seek(w http.ResponseWriter, r *http.Request) {
  162. id := r.URL.Query().Get("id")
  163. channel := r.URL.Query().Get("channel")
  164. streamPath := r.URL.Query().Get("streamPath")
  165. secStr := r.URL.Query().Get("second")
  166. sec, err := strconv.ParseUint(secStr, 10, 32)
  167. if err != nil {
  168. util.ReturnError(util.APIErrorQueryParse, "second parameter is invalid: "+err.Error(), w, r)
  169. return
  170. }
  171. if c := FindChannel(id, channel); c != nil {
  172. util.ReturnError(0, fmt.Sprintf("play code:%d", c.PlayAt(streamPath, uint(sec))), w, r)
  173. } else {
  174. util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
  175. }
  176. }
  177. func (c *GB28181Config) API_play_forward(w http.ResponseWriter, r *http.Request) {
  178. id := r.URL.Query().Get("id")
  179. channel := r.URL.Query().Get("channel")
  180. streamPath := r.URL.Query().Get("streamPath")
  181. speedStr := r.URL.Query().Get("speed")
  182. speed, err := strconv.ParseFloat(speedStr, 32)
  183. secondErrMsg := "speed parameter is invalid, should be one of 0.25,0.5,1,2,4"
  184. if err != nil || !playScaleValues[float32(speed)] {
  185. util.ReturnError(util.APIErrorQueryParse, secondErrMsg, w, r)
  186. return
  187. }
  188. if c := FindChannel(id, channel); c != nil {
  189. util.ReturnError(0, fmt.Sprintf("playforward code:%d", c.PlayForward(streamPath, float32(speed))), w, r)
  190. } else {
  191. util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
  192. }
  193. }
  194. func (c *GB28181Config) API_position(w http.ResponseWriter, r *http.Request) {
  195. //CORS(w, r)
  196. query := r.URL.Query()
  197. //设备id
  198. id := query.Get("id")
  199. //订阅周期(单位:秒)
  200. expires := query.Get("expires")
  201. //订阅间隔(单位:秒)
  202. interval := query.Get("interval")
  203. expiresInt, err := time.ParseDuration(expires)
  204. if expires == "" || err != nil {
  205. expiresInt = c.Position.Expires
  206. }
  207. intervalInt, err := time.ParseDuration(interval)
  208. if interval == "" || err != nil {
  209. intervalInt = c.Position.Interval
  210. }
  211. if v, ok := Devices.Load(id); ok {
  212. d := v.(*Device)
  213. util.ReturnError(0, fmt.Sprintf("mobileposition code:%d", d.MobilePositionSubscribe(id, expiresInt, intervalInt)), w, r)
  214. } else {
  215. util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q not found", id), w, r)
  216. }
  217. }
  218. type DevicePosition struct {
  219. ID string
  220. GpsTime time.Time //gps时间
  221. Longitude string //经度
  222. Latitude string //纬度
  223. }
  224. func (c *GB28181Config) API_get_position(w http.ResponseWriter, r *http.Request) {
  225. query := r.URL.Query()
  226. //设备id
  227. id := query.Get("id")
  228. if query.Get("interval") == "" {
  229. query.Set("interval", fmt.Sprintf("%ds", c.Position.Interval.Seconds()))
  230. }
  231. util.ReturnFetchValue(func() (list []*DevicePosition) {
  232. if id == "" {
  233. Devices.Range(func(key, value interface{}) bool {
  234. d := value.(*Device)
  235. if time.Since(d.GpsTime) <= c.Position.Interval {
  236. list = append(list, &DevicePosition{ID: d.ID, GpsTime: d.GpsTime, Longitude: d.Longitude, Latitude: d.Latitude})
  237. }
  238. return true
  239. })
  240. } else if v, ok := Devices.Load(id); ok {
  241. d := v.(*Device)
  242. list = append(list, &DevicePosition{ID: d.ID, GpsTime: d.GpsTime, Longitude: d.Longitude, Latitude: d.Latitude})
  243. }
  244. return
  245. }, w, r)
  246. }