50 files modified
1 files renamed
50 files added
| | |
| | | "header": [], |
| | | "body": { |
| | | "mode": "raw", |
| | | "raw": "{\r\n \"url\": \"rtmp://192.168.1.1/live/1651053434895\",\r\n \"url_type\": 1,\r\n \"video_id\": \"1581F4BN/52-0-0/zoom-0\",\r\n \"video_quality\": 0\r\n}", |
| | | "raw": "{\r\n \"url\": \"rtmp://192.168.1.1/live/1651053434895\",\r\n \"url_type\": 1,\r\n \"video_id\": \"1581F5B0159/53-0-0/normal-0\",\r\n \"video_quality\": 0\r\n}", |
| | | "options": { |
| | | "raw": { |
| | | "language": "json" |
| | |
| | | } |
| | | }, |
| | | "response": [] |
| | | }, |
| | | { |
| | | "name": "Firmware Upgrad", |
| | | "request": { |
| | | "method": "POST", |
| | | "header": [], |
| | | "body": { |
| | | "mode": "raw", |
| | | "raw": "[\r\n {\r\n \"sn\": \"1581F5B9\",\r\n \"device_name\": \"Matrice 30\",\r\n \"product_version\": \"04.01.0020\",\r\n \"firmware_upgrade_type\": 3\r\n }\r\n]\r\n", |
| | | "options": { |
| | | "raw": { |
| | | "language": "json" |
| | | } |
| | | } |
| | | }, |
| | | "url": { |
| | | "raw": "{{base_url}}{{manage_version}}/devices/{{workspace_id}}/devices/ota", |
| | | "host": [ |
| | | "{{base_url}}{{manage_version}}" |
| | | ], |
| | | "path": [ |
| | | "devices", |
| | | "{{workspace_id}}", |
| | | "devices", |
| | | "ota" |
| | | ] |
| | | } |
| | | }, |
| | | "response": [] |
| | | }, |
| | | { |
| | | "name": "Get Latest Release Note", |
| | | "request": { |
| | | "method": "GET", |
| | | "header": [], |
| | | "url": { |
| | | "raw": "{{base_url}}{{manage_version}}/workspaces/firmware-release-notes/latest?device_name=DJI Dock", |
| | | "host": [ |
| | | "{{base_url}}{{manage_version}}" |
| | | ], |
| | | "path": [ |
| | | "workspaces", |
| | | "firmware-release-notes", |
| | | "latest" |
| | | ], |
| | | "query": [ |
| | | { |
| | | "key": "device_name", |
| | | "value": "DJI Dock" |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | "response": [] |
| | | }, |
| | | { |
| | | "name": "Get HMS Info", |
| | | "request": { |
| | | "method": "GET", |
| | | "header": [], |
| | | "url": { |
| | | "raw": "{{base_url}}{{manage_version}}/devices/{{workspace_id}}/devices/hms?device_sn=&language=en&page=1&page_size=2", |
| | | "host": [ |
| | | "{{base_url}}{{manage_version}}" |
| | | ], |
| | | "path": [ |
| | | "devices", |
| | | "{{workspace_id}}", |
| | | "devices", |
| | | "hms" |
| | | ], |
| | | "query": [ |
| | | { |
| | | "key": "device_sn", |
| | | "value": "", |
| | | "description": "Type: List" |
| | | }, |
| | | { |
| | | "key": "begin_time", |
| | | "value": null, |
| | | "disabled": true |
| | | }, |
| | | { |
| | | "key": "end_time", |
| | | "value": null, |
| | | "disabled": true |
| | | }, |
| | | { |
| | | "key": "language", |
| | | "value": "en", |
| | | "description": "zh or en" |
| | | }, |
| | | { |
| | | "key": "message", |
| | | "value": null, |
| | | "disabled": true |
| | | }, |
| | | { |
| | | "key": "page", |
| | | "value": "1" |
| | | }, |
| | | { |
| | | "key": "page_size", |
| | | "value": "2" |
| | | }, |
| | | { |
| | | "key": "level", |
| | | "value": null, |
| | | "disabled": true |
| | | }, |
| | | { |
| | | "key": "update_time", |
| | | "value": null, |
| | | "description": "Type: Long", |
| | | "disabled": true |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | "response": [] |
| | | }, |
| | | { |
| | | "name": "Update Unread HMS", |
| | | "request": { |
| | | "method": "PUT", |
| | | "header": [], |
| | | "url": { |
| | | "raw": "{{base_url}}{{manage_version}}/devices/{{workspace_id}}/devices/hms/{{device_sn}}", |
| | | "host": [ |
| | | "{{base_url}}{{manage_version}}" |
| | | ], |
| | | "path": [ |
| | | "devices", |
| | | "{{workspace_id}}", |
| | | "devices", |
| | | "hms", |
| | | "{{device_sn}}" |
| | | ] |
| | | } |
| | | }, |
| | | "response": [] |
| | | }, |
| | | { |
| | | "name": "Get Unread Hms", |
| | | "request": { |
| | | "method": "GET", |
| | | "header": [], |
| | | "url": { |
| | | "raw": "{{base_url}}{{manage_version}}/devices/{{workspace_id}}/devices/hms/{{device_sn}}", |
| | | "host": [ |
| | | "{{base_url}}{{manage_version}}" |
| | | ], |
| | | "path": [ |
| | | "devices", |
| | | "{{workspace_id}}", |
| | | "devices", |
| | | "hms", |
| | | "{{device_sn}}" |
| | | ] |
| | | } |
| | | }, |
| | | "response": [] |
| | | }, |
| | | { |
| | | "name": "Get Uploaded Logs", |
| | | "request": { |
| | | "method": "GET", |
| | | "header": [], |
| | | "url": { |
| | | "raw": "{{base_url}}{{manage_version}}/workspaces/{{workspace_id}}/devices/{{device_sn}}/logs-uploaded?page=1&page_size=12&begin_time=123123&end_time=123123", |
| | | "host": [ |
| | | "{{base_url}}{{manage_version}}" |
| | | ], |
| | | "path": [ |
| | | "workspaces", |
| | | "{{workspace_id}}", |
| | | "devices", |
| | | "{{device_sn}}", |
| | | "logs-uploaded" |
| | | ], |
| | | "query": [ |
| | | { |
| | | "key": "page", |
| | | "value": "1" |
| | | }, |
| | | { |
| | | "key": "page_size", |
| | | "value": "12" |
| | | }, |
| | | { |
| | | "key": "status", |
| | | "value": null, |
| | | "disabled": true |
| | | }, |
| | | { |
| | | "key": "begin_time", |
| | | "value": "123123" |
| | | }, |
| | | { |
| | | "key": "end_time", |
| | | "value": "123123" |
| | | }, |
| | | { |
| | | "key": "logs_information", |
| | | "value": "", |
| | | "disabled": true |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | "response": [] |
| | | }, |
| | | { |
| | | "name": "Get Real Time Logs", |
| | | "request": { |
| | | "method": "GET", |
| | | "header": [], |
| | | "url": { |
| | | "raw": "{{base_url}}{{manage_version}}/workspaces/{{workspace_id}}/devices/{{device_sn}}/logs?domain_list=0,3", |
| | | "host": [ |
| | | "{{base_url}}{{manage_version}}" |
| | | ], |
| | | "path": [ |
| | | "workspaces", |
| | | "{{workspace_id}}", |
| | | "devices", |
| | | "{{device_sn}}", |
| | | "logs" |
| | | ], |
| | | "query": [ |
| | | { |
| | | "key": "domain_list", |
| | | "value": "0,3" |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | "response": [] |
| | | }, |
| | | { |
| | | "name": "Upload Logs", |
| | | "request": { |
| | | "method": "POST", |
| | | "header": [], |
| | | "body": { |
| | | "mode": "raw", |
| | | "raw": "{\r\n \"logs_information\":\"\",\r\n \"happen_time\":1659326597,\r\n \"files\":[\r\n {\r\n \"list\":[\r\n {\r\n \"boot_index\":1053,\r\n \"end_time\":1662070409,\r\n \"size\":1083590875,\r\n \"start_time\":1662066809\r\n }\r\n ],\r\n \"device_sn\":\"4TADK1D\",\r\n \"module\":\"3\"\r\n },\r\n {\r\n \"list\":[\r\n {\r\n \"boot_index\":222,\r\n \"end_time\":1661833032,\r\n \"size\":1782411613,\r\n \"start_time\":1661830103\r\n }\r\n ],\r\n \"device_sn\":\"1581259\",\r\n \"module\":\"0\"\r\n }\r\n ]\r\n}", |
| | | "options": { |
| | | "raw": { |
| | | "language": "json" |
| | | } |
| | | } |
| | | }, |
| | | "url": { |
| | | "raw": "{{base_url}}{{manage_version}}/workspaces/{{workspace_id}}/devices/{{device_sn}}/logs", |
| | | "host": [ |
| | | "{{base_url}}{{manage_version}}" |
| | | ], |
| | | "path": [ |
| | | "workspaces", |
| | | "{{workspace_id}}", |
| | | "devices", |
| | | "{{device_sn}}", |
| | | "logs" |
| | | ] |
| | | } |
| | | }, |
| | | "response": [] |
| | | }, |
| | | { |
| | | "name": "Cancel File Upload", |
| | | "request": { |
| | | "method": "DELETE", |
| | | "header": [], |
| | | "body": { |
| | | "mode": "raw", |
| | | "raw": "{\r\n \"status\":\"cancel\",\r\n \"module_list\":[\r\n \"0\",\r\n \"3\"\r\n ]\r\n}", |
| | | "options": { |
| | | "raw": { |
| | | "language": "json" |
| | | } |
| | | } |
| | | }, |
| | | "url": { |
| | | "raw": "{{base_url}}{{manage_version}}/workspaces/{{workspace_id}}/devices/{{device_sn}}/logs", |
| | | "host": [ |
| | | "{{base_url}}{{manage_version}}" |
| | | ], |
| | | "path": [ |
| | | "workspaces", |
| | | "{{workspace_id}}", |
| | | "devices", |
| | | "{{device_sn}}", |
| | | "logs" |
| | | ] |
| | | } |
| | | }, |
| | | "response": [] |
| | | }, |
| | | { |
| | | "name": "Delete Upload History", |
| | | "request": { |
| | | "method": "DELETE", |
| | | "header": [], |
| | | "url": { |
| | | "raw": "{{base_url}}{{manage_version}}/workspaces/{{workspace_id}}/devices/{{device_sn}}/logs/{{logs_id}}", |
| | | "host": [ |
| | | "{{base_url}}{{manage_version}}" |
| | | ], |
| | | "path": [ |
| | | "workspaces", |
| | | "{{workspace_id}}", |
| | | "devices", |
| | | "{{device_sn}}", |
| | | "logs", |
| | | "{{logs_id}}" |
| | | ] |
| | | } |
| | | }, |
| | | "response": [] |
| | | } |
| | | ], |
| | | "auth": { |
| | |
| | | "apikey": [ |
| | | { |
| | | "key": "value", |
| | | "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTI2OTUxOTcsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTI3ODE1OTcsImlhdCI6MTY1MjY5NTE5NywidXNlcm5hbWUiOiJhZG1pblBDIn0.BHTwW8imw5ab0GUypRyJ2gkoz5av9q99NrxoFlL53dA", |
| | | "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NjM1NTkxMTAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NjM2NDU1MTAsImlhdCI6MTY2MzU1OTExMCwidXNlcm5hbWUiOiJhZG1pblBDIn0.LG1JXZkuTdMaqnXn5WMJvnysNkHHbc4HLe_qZPWz_nM", |
| | | "type": "string" |
| | | }, |
| | | { |
| | |
| | | "apikey": [ |
| | | { |
| | | "key": "value", |
| | | "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTgzOTIyNzksImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTg0Nzg2NzksImlhdCI6MTY1ODM5MjI3OSwidXNlcm5hbWUiOiJhZG1pblBDIn0.ErClyQS1YzoQVBcLYxpFEiyFTb1L-eg2-vsudlL9WJU", |
| | | "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NjI2OTYwNjMsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NjI3ODI0NjMsImlhdCI6MTY2MjY5NjA2MywidXNlcm5hbWUiOiJhZG1pblBDIn0.9XEd-Zspb_a-2WhtcHxbQ4GdHbBj9wfmUbHBkZgSS0c", |
| | | "type": "string" |
| | | }, |
| | | { |
| | |
| | | "apikey": [ |
| | | { |
| | | "key": "value", |
| | | "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTI2OTUxOTcsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTI3ODE1OTcsImlhdCI6MTY1MjY5NTE5NywidXNlcm5hbWUiOiJhZG1pblBDIn0.BHTwW8imw5ab0GUypRyJ2gkoz5av9q99NrxoFlL53dA", |
| | | "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTg3MTgxNTMsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTg4MDQ1NTMsImlhdCI6MTY1ODcxODE1MywidXNlcm5hbWUiOiJhZG1pblBDIn0._Xw3rnnDhs32JW9pD_FBtRWDuwLZgX_ys3GNmZxuHsk", |
| | | "type": "string" |
| | | }, |
| | | { |
| | |
| | | "header": [], |
| | | "body": { |
| | | "mode": "raw", |
| | | "raw": "{\r\n \"name\": \"\",\r\n \"fild_id\": \"\",\r\n \"dock_sn\": \"\",\r\n \"type\": \"\",\r\n \"immediate\": false\r\n}", |
| | | "raw": "{\r\n \"name\": \"\",\r\n \"file_id\": \"\",\r\n \"dock_sn\": \"\",\r\n \"type\": \"\",\r\n \"immediate\": false\r\n}", |
| | | "options": { |
| | | "raw": { |
| | | "language": "json" |
| | |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "name": "control", |
| | | "item": [ |
| | | { |
| | | "name": "Create Control Job", |
| | | "request": { |
| | | "method": "POST", |
| | | "header": [], |
| | | "url": { |
| | | "raw": "{{base_url}}{{control_version}}/devices/4TADK7E000000H/jobs/debug_mode_close", |
| | | "host": [ |
| | | "{{base_url}}{{control_version}}" |
| | | ], |
| | | "path": [ |
| | | "devices", |
| | | "4TADK7E000000H", |
| | | "jobs", |
| | | "debug_mode_close" |
| | | ] |
| | | } |
| | | }, |
| | | "response": [] |
| | | } |
| | | ], |
| | | "auth": { |
| | | "type": "apikey", |
| | | "apikey": [ |
| | | { |
| | | "key": "value", |
| | | "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NjE5NTQwMTQsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NjIwNDA0MTQsImlhdCI6MTY2MTk1NDAxNCwidXNlcm5hbWUiOiJhZG1pblBDIn0.GgCh575h2-HvYvdGZIKBW50r0F6CPACQn4ceAVzJfCU", |
| | | "type": "string" |
| | | }, |
| | | { |
| | | "key": "key", |
| | | "value": "x-auth-token", |
| | | "type": "string" |
| | | } |
| | | ] |
| | | }, |
| | | "event": [ |
| | | { |
| | | "listen": "prerequest", |
| | | "script": { |
| | | "type": "text/javascript", |
| | | "exec": [ |
| | | "" |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | | "listen": "test", |
| | | "script": { |
| | | "type": "text/javascript", |
| | | "exec": [ |
| | | "" |
| | | ] |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | "auth": { |
| | |
| | | "apikey": [ |
| | | { |
| | | "key": "value", |
| | | "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTA0MjY3MzAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTA1MTMxMzAsImlhdCI6MTY1MDQyNjczMCwidXNlcm5hbWUiOiJhZG1pblBDIn0.-FBpi0ktuZ68jV6-HQ7mwm8iC07YH-Hw2aRiREzJ8hs", |
| | | "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NjMyMjM1MTAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NjMzMDk5MTAsImlhdCI6MTY2MzIyMzUxMCwidXNlcm5hbWUiOiJhZG1pblBDIn0.6gzNuuX2f0YBoddoD61NFnwABQ_X4LFtQhEaLWSmTW8", |
| | | "type": "string" |
| | | }, |
| | | { |
| | |
| | | "key": "storage_version", |
| | | "value": "/storage/api/v1", |
| | | "enabled": true |
| | | }, |
| | | { |
| | | "key": "control_version", |
| | | "value": "/control/api/v1", |
| | | "type": "default", |
| | | "enabled": true |
| | | }, |
| | | { |
| | | "key": "device_sn", |
| | | "value": "xxxxxxxxxx", |
| | | "type": "default", |
| | | "enabled": true |
| | | } |
| | | ], |
| | | "_postman_variable_scope": "environment", |
| | | "_postman_exported_at": "2022-07-21T08:35:48.441Z", |
| | | "_postman_exported_using": "Postman/9.19.0" |
| | | "_postman_exported_at": "2022-09-23T03:53:25.999Z", |
| | | "_postman_exported_using": "Postman/9.31.0" |
| | | } |
| | |
| | | return new DirectChannel(); |
| | | } |
| | | |
| | | @Bean(name = ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS) |
| | | public MessageChannel eventsControlProgress() { |
| | | return new DirectChannel(); |
| | | } |
| | | |
| | | @Bean(name = ChannelName.INBOUND_EVENTS_OTA_PROGRESS) |
| | | public MessageChannel eventsOtaProgress() { |
| | | return new DirectChannel(); |
| | | } |
| | | |
| | | @Bean(name = ChannelName.INBOUND_EVENTS_FILE_UPLOAD_PROGRESS) |
| | | public MessageChannel eventsFileUploadProgress() { |
| | | return new DirectChannel(); |
| | | } |
| | | |
| | | } |
| | |
| | | import org.springframework.integration.dsl.IntegrationFlows; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * @author sean |
| | |
| | | }) |
| | | .<CommonTopicReceiver, EventsMethodEnum>route( |
| | | receiver -> EventsMethodEnum.find(receiver.getMethod()), |
| | | mapping -> { |
| | | mapping.channelMapping(EventsMethodEnum.FILE_UPLOAD_CALLBACK, ChannelName.INBOUND_EVENTS_FILE_UPLOAD_CALLBACK); |
| | | mapping.channelMapping(EventsMethodEnum.FLIGHT_TASK_PROGRESS, ChannelName.INBOUND_EVENTS_FLIGHT_TASK_PROGRESS); |
| | | mapping.channelMapping(EventsMethodEnum.HMS, ChannelName.INBOUND_EVENTS_HMS); |
| | | mapping.channelMapping(EventsMethodEnum.UNKNOWN, ChannelName.DEFAULT); |
| | | }) |
| | | mapping -> Arrays.stream(EventsMethodEnum.values()).forEach( |
| | | methodEnum -> mapping.channelMapping(methodEnum, methodEnum.getChannelName()))) |
| | | .get(); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dji.sample.component.mqtt.handler; |
| | | |
| | | import com.dji.sample.component.mqtt.model.*; |
| | | import com.dji.sample.manage.model.receiver.LogsFileUploadList; |
| | | import com.fasterxml.jackson.core.type.TypeReference; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.integration.annotation.ServiceActivator; |
| | | import org.springframework.messaging.Message; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/9 |
| | | */ |
| | | @Component |
| | | public class ServicesReplyHandler { |
| | | |
| | | @Autowired |
| | | private ObjectMapper mapper; |
| | | |
| | | /** |
| | | * Handle the reply message from the pilot side to the on-demand video. |
| | | * @param message reply message |
| | | * @throws IOException |
| | | */ |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_SERVICE_REPLY) |
| | | public void serviceReply(Message<?> message) throws IOException { |
| | | byte[] payload = (byte[])message.getPayload(); |
| | | |
| | | CommonTopicReceiver receiver = mapper.readValue(payload, new TypeReference<CommonTopicReceiver>() {}); |
| | | if (ServicesMethodEnum.FILE_UPLOAD_LIST.getMethod().equals(receiver.getMethod())) { |
| | | LogsFileUploadList list = mapper.convertValue(receiver.getData(), new TypeReference<LogsFileUploadList>() {}); |
| | | receiver.setData(list); |
| | | } else { |
| | | ServiceReply reply = mapper.convertValue(receiver.getData(), new TypeReference<ServiceReply>() {}); |
| | | receiver.setData(reply); |
| | | } |
| | | Chan<CommonTopicReceiver<?>> chan = Chan.getInstance(); |
| | | // Put the message to the chan object. |
| | | chan.put(receiver); |
| | | } |
| | | } |
| | |
| | | */ |
| | | public class Chan<T> { |
| | | |
| | | private static final long THREAD_WAIT_TIME = 1000_000 * 2000; |
| | | private static final long THREAD_WAIT_TIME = 1000_000L * 10_000; |
| | | |
| | | private volatile T data; |
| | | |
| | |
| | | public static final String INBOUND_REQUESTS_AIRPORT_ORGANIZATION_BIND = "inboundRequestsAirportOrganizationBind"; |
| | | |
| | | public static final String INBOUND_EVENTS_HMS = "inboundEventsHms"; |
| | | |
| | | public static final String INBOUND_EVENTS_CONTROL_PROGRESS = "inboundEventsControlProgress"; |
| | | |
| | | public static final String INBOUND_EVENTS_OTA_PROGRESS = "inboundEventsOtaProgress"; |
| | | |
| | | public static final String INBOUND_EVENTS_FILE_UPLOAD_PROGRESS = "inboundEventsFileUploadProgress"; |
| | | } |
| | |
| | | */ |
| | | public enum EventsMethodEnum { |
| | | |
| | | FLIGHT_TASK_PROGRESS("flighttask_progress"), |
| | | FLIGHT_TASK_PROGRESS("flighttask_progress", ChannelName.INBOUND_EVENTS_FLIGHT_TASK_PROGRESS), |
| | | |
| | | FILE_UPLOAD_CALLBACK("file_upload_callback"), |
| | | FILE_UPLOAD_CALLBACK("file_upload_callback", ChannelName.INBOUND_EVENTS_FILE_UPLOAD_CALLBACK), |
| | | |
| | | HMS("hms"), |
| | | HMS("hms", ChannelName.INBOUND_EVENTS_HMS), |
| | | |
| | | UNKNOWN("Unknown"); |
| | | DEVICE_REBOOT("device_reboot", ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS), |
| | | |
| | | DRONE_OPEN("drone_open", ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS), |
| | | |
| | | DRONE_CLOSE("drone_close", ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS), |
| | | |
| | | DEVICE_CHECK("device_check", ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS), |
| | | |
| | | DRONE_FORMAT("drone_format", ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS), |
| | | |
| | | DEVICE_FORMAT("device_format", ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS), |
| | | |
| | | COVER_OPEN("cover_open", ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS), |
| | | |
| | | COVER_CLOSE("cover_close", ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS), |
| | | |
| | | PUTTER_OPEN("putter_open", ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS), |
| | | |
| | | PUTTER_CLOSE("putter_close", ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS), |
| | | |
| | | CHARGE_OPEN("charge_open", ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS), |
| | | |
| | | CHARGE_CLOSE("charge_close", ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS), |
| | | |
| | | OTA_PROGRESS("ota_progress", ChannelName.INBOUND_EVENTS_OTA_PROGRESS), |
| | | |
| | | FILE_UPLOAD_PROGRESS("fileupload_progress", ChannelName.INBOUND_EVENTS_FILE_UPLOAD_PROGRESS), |
| | | |
| | | UNKNOWN("Unknown", ChannelName.DEFAULT); |
| | | |
| | | private String method; |
| | | |
| | | EventsMethodEnum(String method) { |
| | | private String channelName; |
| | | |
| | | EventsMethodEnum(String method, String channelName) { |
| | | this.method = method; |
| | | this.channelName = channelName; |
| | | } |
| | | |
| | | public String getMethod() { |
| | | return method; |
| | | } |
| | | |
| | | public String getChannelName() { |
| | | return channelName; |
| | | } |
| | | |
| | | public static EventsMethodEnum find(String method) { |
| | | return Arrays.stream(EventsMethodEnum.values()) |
| | | .filter(methodEnum -> methodEnum.method.equals(method)) |
| New file |
| | |
| | | package com.dji.sample.component.mqtt.model; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/7/29 |
| | | */ |
| | | @Data |
| | | public class EventsOutputReceiver { |
| | | |
| | | private String status; |
| | | |
| | | private OutputProgressReceiver progress; |
| | | } |
| | |
| | | |
| | | private String bid; |
| | | |
| | | private String sn; |
| | | |
| | | } |
| New file |
| | |
| | | package com.dji.sample.component.mqtt.model; |
| | | |
| | | import lombok.Getter; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/8/17 |
| | | */ |
| | | @Getter |
| | | public enum EventsResultStatusEnum { |
| | | |
| | | SENT("sent", false), |
| | | |
| | | IN_PROGRESS("in_progress", false), |
| | | |
| | | OK("ok", true), |
| | | |
| | | PAUSED("paused", false), |
| | | |
| | | REJECTED("rejected", true), |
| | | |
| | | FAILED("failed", true), |
| | | |
| | | CANCELED("canceled", true), |
| | | |
| | | TIMEOUT("timeout", true), |
| | | |
| | | UNKNOWN("unknown", false); |
| | | |
| | | String desc; |
| | | |
| | | Boolean end; |
| | | |
| | | EventsResultStatusEnum(String desc, Boolean end) { |
| | | this.desc = desc; |
| | | this.end = end; |
| | | } |
| | | |
| | | public static EventsResultStatusEnum find(String desc) { |
| | | return Arrays.stream(EventsResultStatusEnum.values()) |
| | | .filter(status -> status.desc.equals(desc)) |
| | | .findFirst().orElse(UNKNOWN); |
| | | } |
| | | } |
| | |
| | | public static final String BIND_STATUS = "bind_status"; |
| | | |
| | | public static final String LIST = "list"; |
| | | |
| | | public static final String MODULE_LIST = "module_list"; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.component.mqtt.model; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/7/29 |
| | | */ |
| | | @Data |
| | | public class OutputProgressReceiver { |
| | | |
| | | private Integer percent; |
| | | |
| | | private String stepKey; |
| | | |
| | | private Integer stepResult; |
| | | } |
| | |
| | | package com.dji.sample.component.mqtt.model; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * @author sean.zhou |
| | | * @date 2021/11/22 |
| | |
| | | */ |
| | | public enum ServicesMethodEnum { |
| | | |
| | | LIVE_START_PUSH("live_start_push"), |
| | | LIVE_START_PUSH("live_start_push", false), |
| | | |
| | | LIVE_STOP_PUSH("live_stop_push"), |
| | | LIVE_STOP_PUSH("live_stop_push", false), |
| | | |
| | | LIVE_SET_QUALITY("live_set_quality"), |
| | | LIVE_SET_QUALITY("live_set_quality", false), |
| | | |
| | | FLIGHTTASK_CREATE("flighttask_create"), |
| | | FLIGHTTASK_CREATE("flighttask_create", false), |
| | | |
| | | UNKNOWN("unknown"); |
| | | DEBUG_MODE_OPEN("debug_mode_open", false), |
| | | |
| | | DEBUG_MODE_CLOSE("debug_mode_close", false), |
| | | |
| | | SUPPLEMENT_LIGHT_OPEN("supplement_light_open", false), |
| | | |
| | | SUPPLEMENT_LIGHT_CLOSE("supplement_light_close", false), |
| | | |
| | | RETURN_HOME("return_home", false), |
| | | |
| | | SDR_WORKMODE_SWITCH("sdr_workmode_switch", false), |
| | | |
| | | DEVICE_REBOOT("device_reboot", true), |
| | | |
| | | DRONE_OPEN("drone_open", true), |
| | | |
| | | DRONE_CLOSE("drone_close", true), |
| | | |
| | | DEVICE_CHECK("device_check", true), |
| | | |
| | | DRONE_FORMAT("drone_format", true), |
| | | |
| | | DEVICE_FORMAT("device_format", true), |
| | | |
| | | COVER_OPEN("cover_open", true), |
| | | |
| | | COVER_CLOSE("cover_close", true), |
| | | |
| | | PUTTER_OPEN("putter_open", true), |
| | | |
| | | PUTTER_CLOSE("putter_close", true), |
| | | |
| | | CHARGE_OPEN("charge_open", true), |
| | | |
| | | CHARGE_CLOSE("charge_close", true), |
| | | |
| | | OTA_CREATE("ota_create", true), |
| | | |
| | | FILE_UPLOAD_LIST("fileupload_list", false), |
| | | |
| | | FILE_UPLOAD_START("fileupload_start", true), |
| | | |
| | | FILE_UPLOAD_UPDATE("fileupload_update", false), |
| | | |
| | | UNKNOWN("unknown", false); |
| | | |
| | | private String method; |
| | | |
| | | ServicesMethodEnum(String method) { |
| | | private Boolean progress; |
| | | |
| | | ServicesMethodEnum(String method, Boolean progress) { |
| | | this.method = method; |
| | | this.progress = progress; |
| | | } |
| | | |
| | | public static ServicesMethodEnum find(String method) { |
| | | return Arrays.stream(ServicesMethodEnum.values()) |
| | | .filter(methodEnum -> methodEnum.method.equals(method)) |
| | | .findAny() |
| | | .orElse(UNKNOWN); |
| | | } |
| | | |
| | | public String getMethod() { |
| | | return method; |
| | | } |
| | | |
| | | public Boolean getProgress() { |
| | | return progress; |
| | | } |
| | | } |
| | |
| | | void publish(String topic, int qos, CommonTopicResponse response); |
| | | |
| | | /** |
| | | * Send live streaming start message and receive a response at the same time |
| | | * Send live streaming start message and receive a response at the same time. |
| | | * @param topic |
| | | * @param response notification of whether the start is successful. |
| | | * @return |
| | | */ |
| | | Optional<ServiceReply> publishWithReply(String topic, CommonTopicResponse response); |
| | | |
| | | /** |
| | | * Send live streaming start message and receive a response at the same time. |
| | | * @param clazz |
| | | * @param topic |
| | | * @param response |
| | | * @param retryTime |
| | | * @param <T> |
| | | * @return |
| | | */ |
| | | <T> Optional<T> publishWithReply(Class<T> clazz, String topic, CommonTopicResponse response, int retryTime); |
| | | } |
| | |
| | | } |
| | | |
| | | public Optional<ServiceReply> publishWithReply(String topic, CommonTopicResponse response) { |
| | | return this.publishWithReply(ServiceReply.class, topic, response, 2); |
| | | } |
| | | |
| | | public <T> Optional<T> publishWithReply(Class<T> clazz, String topic, CommonTopicResponse response, int retryTime) { |
| | | AtomicInteger time = new AtomicInteger(0); |
| | | // Retry three times |
| | | while (time.getAndIncrement() < 3) { |
| | | while (time.getAndIncrement() < retryTime) { |
| | | this.publish(topic, response); |
| | | |
| | | Chan<CommonTopicReceiver<ServiceReply>> chan = Chan.getInstance(); |
| | | Chan<CommonTopicReceiver<T>> chan = Chan.getInstance(); |
| | | // If the message is not received in 0.5 seconds then resend it again. |
| | | CommonTopicReceiver<ServiceReply> receiver = chan.get(response.getMethod()); |
| | | CommonTopicReceiver<T> receiver = chan.get(response.getMethod()); |
| | | if (receiver == null) { |
| | | continue; |
| | | } |
| | |
| | | |
| | | AWS("aws"), |
| | | |
| | | /* |
| | | * MinIO is temporarily unavailable. |
| | | */ |
| | | MINIO("minio"); |
| | | |
| | | private String type; |
| | |
| | | |
| | | import com.aliyun.oss.OSS; |
| | | import com.aliyun.oss.OSSClientBuilder; |
| | | import com.aliyun.oss.OSSException; |
| | | import com.aliyun.oss.model.OSSObject; |
| | | import com.aliyuncs.DefaultAcsClient; |
| | | import com.aliyuncs.IAcsClient; |
| | |
| | | } |
| | | OSS ossClient = this.createClient(); |
| | | // First check if the object can be fetched. |
| | | ossClient.getObject(bucket, objectKey); |
| | | boolean isExist = ossClient.doesObjectExist(bucket, objectKey); |
| | | if (!isExist) { |
| | | throw new OSSException("The object does not exist."); |
| | | } |
| | | |
| | | return ossClient.generatePresignedUrl(bucket, objectKey, |
| | | new Date(System.currentTimeMillis() + configuration.getExpire() * 1000)); |
| | |
| | | @Override |
| | | public Boolean deleteObject(String bucket, String objectKey) { |
| | | OSS ossClient = this.createClient(); |
| | | if (!ossClient.doesObjectExist(bucket, objectKey)) { |
| | | ossClient.shutdown(); |
| | | return true; |
| | | } |
| | | ossClient.deleteObject(bucket, objectKey); |
| | | ossClient.shutdown(); |
| | | return true; |
| | |
| | | public byte[] getObject(String bucket, String objectKey) { |
| | | OSS ossClient = this.createClient(); |
| | | OSSObject object = ossClient.getObject(bucket, objectKey); |
| | | InputStream stream = object.getObjectContent(); |
| | | |
| | | try { |
| | | try (InputStream stream = object.getObjectContent()) { |
| | | return stream.readAllBytes(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | try { |
| | | stream.close(); |
| | | ossClient.shutdown(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | ossClient.shutdown(); |
| | | } |
| | | return new byte[0]; |
| | | } |
| | |
| | | @Override |
| | | public Boolean deleteObject(String bucket, String objectKey) { |
| | | AmazonS3 client = this.createClient(); |
| | | if (!client.doesObjectExist(bucket, objectKey)) { |
| | | client.shutdown(); |
| | | return true; |
| | | } |
| | | client.deleteObject(bucket, objectKey); |
| | | client.shutdown(); |
| | | return true; |
| | |
| | | public byte[] getObject(String bucket, String objectKey) { |
| | | AmazonS3 client = this.createClient(); |
| | | S3Object object = client.getObject(bucket, objectKey); |
| | | InputStream stream = object.getObjectContent().getDelegateStream(); |
| | | try { |
| | | |
| | | try (InputStream stream = object.getObjectContent().getDelegateStream()) { |
| | | return stream.readAllBytes(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | try { |
| | | stream.close(); |
| | | client.shutdown(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | client.shutdown(); |
| | | } |
| | | return new byte[0]; |
| | | } |
| | |
| | | import com.dji.sample.component.oss.model.enums.OssTypeEnum; |
| | | import com.dji.sample.component.oss.service.IOssService; |
| | | import com.dji.sample.media.model.CredentialsDTO; |
| | | import io.minio.GetObjectArgs; |
| | | import io.minio.GetPresignedObjectUrlArgs; |
| | | import io.minio.MinioClient; |
| | | import io.minio.RemoveObjectArgs; |
| | | import io.minio.credentials.AssumeRoleProvider; |
| | | import io.minio.errors.*; |
| | | import io.minio.http.Method; |
| | |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.net.URL; |
| | | import java.security.InvalidKeyException; |
| | | import java.security.NoSuchAlgorithmException; |
| | |
| | | AssumeRoleProvider provider = new AssumeRoleProvider(configuration.getEndpoint(), configuration.getAccessKey(), |
| | | configuration.getSecretKey(), Math.toIntExact(configuration.getExpire()), |
| | | null, configuration.getRegion(), null, null, null, null); |
| | | return new CredentialsDTO(provider.fetch(), Math.toIntExact(configuration.getExpire())); |
| | | return new CredentialsDTO(provider.fetch(), configuration.getExpire()); |
| | | } catch (NoSuchAlgorithmException e) { |
| | | log.debug("Failed to obtain sts."); |
| | | e.printStackTrace(); |
| | |
| | | |
| | | @Override |
| | | public Boolean deleteObject(String bucket, String objectKey) { |
| | | return null; |
| | | MinioClient client = this.createClient(); |
| | | try { |
| | | client.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectKey).build()); |
| | | } catch (MinioException | NoSuchAlgorithmException | IOException | InvalidKeyException e) { |
| | | log.error("Failed to delete file."); |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public byte[] getObject(String bucket, String objectKey) { |
| | | MinioClient client = this.createClient(); |
| | | try (InputStream objectResponse = client.getObject(GetObjectArgs.builder().bucket(bucket).object(objectKey).build())) { |
| | | return objectResponse.readAllBytes(); |
| | | } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return new byte[0]; |
| | | } |
| | | |
| | |
| | | |
| | | } |
| | | |
| | | public static final String DELIMITER = ":"; |
| | | |
| | | public static final Integer DEVICE_ALIVE_SECOND = 60; |
| | | |
| | | public static final Integer WEBSOCKET_ALIVE_SECOND = 60 * 60 * 24; |
| | | |
| | | public static final String ONLINE_PREFIX = "online:"; |
| | | public static final String ONLINE_PREFIX = "online" + DELIMITER; |
| | | |
| | | public static final String DEVICE_ONLINE_PREFIX = ONLINE_PREFIX + DeviceDomainEnum.SUB_DEVICE + ":"; |
| | | public static final String DEVICE_ONLINE_PREFIX = ONLINE_PREFIX + DeviceDomainEnum.SUB_DEVICE + DELIMITER; |
| | | |
| | | public static final String WEBSOCKET_PREFIX = "webSocket:"; |
| | | public static final String WEBSOCKET_PREFIX = "webSocket" + DELIMITER; |
| | | |
| | | public static final String WEBSOCKET_ALL = "webSocket:all"; |
| | | public static final String WEBSOCKET_ALL = WEBSOCKET_PREFIX + "all"; |
| | | |
| | | public static final String HMS_PREFIX = "hms:"; |
| | | public static final String HMS_PREFIX = "hms" + DELIMITER; |
| | | |
| | | public static final String FIRMWARE_UPGRADING_PREFIX = "upgrading" + DELIMITER; |
| | | |
| | | public static final String STATE_PAYLOAD_PREFIX = "payload" + DELIMITER; |
| | | |
| | | public static final String LOGS_FILE_PREFIX = "logs_file" + DELIMITER; |
| | | } |
| | |
| | | |
| | | FLIGHT_TASK_PROGRESS("flighttask_progress"), |
| | | |
| | | DEVICE_HMS("device_hms"); |
| | | DEVICE_HMS("device_hms"), |
| | | |
| | | DEVICE_REBOOT("device_reboot"), |
| | | |
| | | DRONE_OPEN("drone_open"), |
| | | |
| | | DRONE_CLOSE("drone_close"), |
| | | |
| | | DEVICE_CHECK("device_check"), |
| | | |
| | | DRONE_FORMAT("drone_format"), |
| | | |
| | | DEVICE_FORMAT("device_format"), |
| | | |
| | | COVER_OPEN("cover_open"), |
| | | |
| | | COVER_CLOSE("cover_close"), |
| | | |
| | | PUTTER_OPEN("putter_open"), |
| | | |
| | | PUTTER_CLOSE("putter_close"), |
| | | |
| | | CHARGE_OPEN("charge_open"), |
| | | |
| | | CHARGE_CLOSE("charge_close"); |
| | | |
| | | private String code; |
| | | |
| | |
| | | return; |
| | | } |
| | | redisOps.hashDel(RedisConst.WEBSOCKET_PREFIX + name[0], new String[] {sessionId}); |
| | | redisOps.hashDel(RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])), new String[] {sessionId}); |
| | | redisOps.hashDel(RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])).getDesc(), new String[] {sessionId}); |
| | | SESSIONS.remove(sessionId); |
| | | } |
| | | |
| | |
| | | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; |
| | | import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; |
| | | import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; |
| | |
| | | public class SpringBeanConfiguration { |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean(ObjectMapper.class) |
| | | // @ConditionalOnMissingBean(ObjectMapper.class) |
| | | public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) { |
| | | ObjectMapper objectMapper = builder.createXmlMapper(false).build(); |
| | | objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); |
| | |
| | | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); |
| | | objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); |
| | | objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); |
| | | objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); |
| | | objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() { |
| | | @Override |
| | | public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { |
| New file |
| | |
| | | package com.dji.sample.configuration.mvc; |
| | | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.WebDataBinder; |
| | | import org.springframework.web.context.request.NativeWebRequest; |
| | | import org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/16 |
| | | */ |
| | | public class GetSnakeArgumentProcessor extends ServletModelAttributeMethodProcessor { |
| | | |
| | | @Autowired |
| | | private GetSnakeDataBinder snakeDataBinder; |
| | | |
| | | /** |
| | | * Class constructor. |
| | | * |
| | | * @param annotationNotRequired if "true", non-simple method arguments and |
| | | * return values are considered model attributes with or without a |
| | | * {@code @ModelAttribute} annotation |
| | | */ |
| | | public GetSnakeArgumentProcessor(boolean annotationNotRequired) { |
| | | super(annotationNotRequired); |
| | | } |
| | | |
| | | @Override |
| | | protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) { |
| | | super.bindRequestParameters(new GetSnakeDataBinder(binder.getTarget(), binder.getObjectName()), request); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dji.sample.configuration.mvc; |
| | | |
| | | import org.springframework.beans.MutablePropertyValues; |
| | | import org.springframework.beans.PropertyValue; |
| | | import org.springframework.web.servlet.mvc.method.annotation.ExtendedServletRequestDataBinder; |
| | | |
| | | import javax.servlet.ServletRequest; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/9 |
| | | */ |
| | | public class GetSnakeDataBinder extends ExtendedServletRequestDataBinder { |
| | | |
| | | public GetSnakeDataBinder(Object target, String objectName) { |
| | | super(target, objectName); |
| | | } |
| | | |
| | | @Override |
| | | protected void addBindValues(MutablePropertyValues mpvs, ServletRequest request) { |
| | | List<PropertyValue> propertyValueList = mpvs.getPropertyValueList(); |
| | | List<PropertyValue> values = new ArrayList<>(propertyValueList); |
| | | for (PropertyValue property : values) { |
| | | String name = convertSnake(property.getName()); |
| | | if (!property.getName().equals(name)) { |
| | | mpvs.addPropertyValue(new PropertyValue(name, property.getValue())); |
| | | propertyValueList.remove(property); |
| | | } |
| | | } |
| | | super.addBindValues(mpvs, request); |
| | | } |
| | | |
| | | private String convertSnake(String key) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | boolean isChange = false; |
| | | for (char c : key.toCharArray()) { |
| | | if (c == '_') { |
| | | isChange = true; |
| | | continue; |
| | | } |
| | | if (isChange) { |
| | | sb.append((char) (c - 32)); |
| | | isChange = false; |
| | | continue; |
| | | } |
| | | sb.append(c); |
| | | } |
| | | return sb.toString(); |
| | | } |
| | | } |
| File was renamed from src/main/java/com/dji/sample/configuration/GlobalMVCConfigurer.java |
| | |
| | | package com.dji.sample.configuration; |
| | | package com.dji.sample.configuration.mvc; |
| | | |
| | | import com.dji.sample.component.AuthInterceptor; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.web.method.support.HandlerMethodArgumentResolver; |
| | | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; |
| | | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
| | | |
| | |
| | | @Value("${url.manage.version}") |
| | | private String manageVersion; |
| | | |
| | | |
| | | @Override |
| | | public void addInterceptors(InterceptorRegistry registry) { |
| | | // Exclude the login interface. |
| | |
| | | // Intercept for all request interfaces. |
| | | registry.addInterceptor(authInterceptor).addPathPatterns("/**").excludePathPatterns(excludePaths); |
| | | } |
| | | |
| | | @Override |
| | | public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { |
| | | resolvers.add(new GetSnakeArgumentProcessor(true)); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dji.sample.control.controller; |
| | | |
| | | import com.dji.sample.common.model.ResponseResult; |
| | | import com.dji.sample.control.service.IControlService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/7/29 |
| | | */ |
| | | @RestController |
| | | @Slf4j |
| | | @RequestMapping("${url.control.prefix}${url.control.version}/devices") |
| | | public class DockController { |
| | | |
| | | @Autowired |
| | | private IControlService controlService; |
| | | |
| | | @PostMapping("/{sn}/jobs/{service_identifier}") |
| | | public ResponseResult createControlJob(@PathVariable String sn, |
| | | @PathVariable("service_identifier") String serviceIdentifier) { |
| | | return controlService.controlDock(sn, serviceIdentifier); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dji.sample.control.service; |
| | | |
| | | import com.dji.sample.common.model.ResponseResult; |
| | | import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
| | | import org.springframework.messaging.MessageHeaders; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/7/29 |
| | | */ |
| | | public interface IControlService { |
| | | |
| | | ResponseResult controlDock(String sn, String serviceIdentifier); |
| | | |
| | | void handleControlProgress(CommonTopicReceiver receiver, MessageHeaders headers); |
| | | |
| | | } |
| New file |
| | |
| | | package com.dji.sample.control.service.impl; |
| | | |
| | | import com.dji.sample.common.model.ResponseResult; |
| | | import com.dji.sample.component.mqtt.model.*; |
| | | import com.dji.sample.component.mqtt.service.IMessageSenderService; |
| | | import com.dji.sample.component.redis.RedisConst; |
| | | import com.dji.sample.component.redis.RedisOpsUtils; |
| | | import com.dji.sample.component.websocket.model.CustomWebSocketMessage; |
| | | import com.dji.sample.component.websocket.service.ISendMessageService; |
| | | import com.dji.sample.component.websocket.service.IWebSocketManageService; |
| | | import com.dji.sample.control.service.IControlService; |
| | | import com.dji.sample.manage.model.dto.DeviceDTO; |
| | | import com.dji.sample.manage.model.enums.UserTypeEnum; |
| | | import com.fasterxml.jackson.core.type.TypeReference; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.integration.annotation.ServiceActivator; |
| | | import org.springframework.integration.mqtt.support.MqttHeaders; |
| | | import org.springframework.messaging.MessageHeaders; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.Optional; |
| | | import java.util.UUID; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/7/29 |
| | | */ |
| | | @Service |
| | | @Slf4j |
| | | public class ControlServiceImpl implements IControlService { |
| | | |
| | | @Autowired |
| | | private RedisOpsUtils redisOps; |
| | | |
| | | @Autowired |
| | | private IMessageSenderService messageSenderService; |
| | | |
| | | @Autowired |
| | | private ISendMessageService webSocketMessageService; |
| | | |
| | | @Autowired |
| | | private IWebSocketManageService webSocketManageService; |
| | | |
| | | @Autowired |
| | | private ObjectMapper mapper; |
| | | |
| | | @Override |
| | | public ResponseResult controlDock(String sn, String serviceIdentifier) { |
| | | ServicesMethodEnum servicesMethodEnum = ServicesMethodEnum.find(serviceIdentifier); |
| | | if (servicesMethodEnum == ServicesMethodEnum.UNKNOWN) { |
| | | return ResponseResult.error("The " + serviceIdentifier + " method does not exist."); |
| | | } |
| | | boolean isExist = redisOps.getExpire(RedisConst.DEVICE_ONLINE_PREFIX + sn) > 0; |
| | | if (!isExist) { |
| | | return ResponseResult.error("The dock is offline."); |
| | | } |
| | | String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + sn + TopicConst.SERVICES_SUF; |
| | | String bid = UUID.randomUUID().toString(); |
| | | Optional<ServiceReply> serviceReplyOpt = messageSenderService.publishWithReply( |
| | | topic, CommonTopicResponse.builder() |
| | | .tid(UUID.randomUUID().toString()) |
| | | .bid(bid) |
| | | .method(serviceIdentifier) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .data("") |
| | | .build()); |
| | | if (serviceReplyOpt.isEmpty()) { |
| | | return ResponseResult.error("No message reply received."); |
| | | } |
| | | ServiceReply<EventsOutputReceiver> serviceReply = mapper.convertValue( |
| | | serviceReplyOpt.get(), new TypeReference<ServiceReply<EventsOutputReceiver>>() {}); |
| | | if (serviceReply.getResult() != ResponseResult.CODE_SUCCESS) { |
| | | return ResponseResult.error(serviceReply.getResult(), serviceReply.getOutput().getStatus()); |
| | | } |
| | | if (servicesMethodEnum.getProgress()) { |
| | | redisOps.setWithExpire(serviceIdentifier + RedisConst.DELIMITER + bid, sn, |
| | | RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND); |
| | | } |
| | | return ResponseResult.success(); |
| | | } |
| | | |
| | | @Override |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_CONTROL_PROGRESS, outputChannel = ChannelName.OUTBOUND) |
| | | public void handleControlProgress(CommonTopicReceiver receiver, MessageHeaders headers) { |
| | | String key = receiver.getMethod() + RedisConst.DELIMITER + receiver.getBid(); |
| | | if (redisOps.getExpire(key) <= 0) { |
| | | return; |
| | | } |
| | | String sn = redisOps.get(key).toString(); |
| | | |
| | | EventsReceiver<EventsOutputReceiver> eventsReceiver = mapper.convertValue(receiver.getData(), |
| | | new TypeReference<EventsReceiver<EventsOutputReceiver>>(){}); |
| | | eventsReceiver.setBid(receiver.getBid()); |
| | | eventsReceiver.setSn(sn); |
| | | |
| | | log.info("SN: {}, {} ===> Control progress: {}", |
| | | sn, receiver.getMethod(), eventsReceiver.getOutput().getProgress().toString()); |
| | | |
| | | if (eventsReceiver.getResult() != ResponseResult.CODE_SUCCESS) { |
| | | log.error("SN: {}, {} ===> Error code: {}", sn, receiver.getMethod(), eventsReceiver.getResult()); |
| | | } |
| | | |
| | | if (eventsReceiver.getOutput().getProgress().getPercent() == 100 || |
| | | EventsResultStatusEnum.find(eventsReceiver.getOutput().getStatus()).getEnd()) { |
| | | redisOps.del(key); |
| | | } |
| | | |
| | | DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + sn); |
| | | webSocketMessageService.sendBatch( |
| | | webSocketManageService.getValueWithWorkspaceAndUserType( |
| | | device.getWorkspaceId(), UserTypeEnum.WEB.getVal()), |
| | | CustomWebSocketMessage.builder() |
| | | .data(eventsReceiver) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .bizCode(receiver.getMethod()) |
| | | .build()); |
| | | |
| | | if (receiver.getNeedReply() != null && receiver.getNeedReply() == 1) { |
| | | String topic = headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF; |
| | | messageSenderService.publish(topic, |
| | | CommonTopicResponse.builder() |
| | | .tid(receiver.getTid()) |
| | | .bid(receiver.getBid()) |
| | | .method(receiver.getMethod()) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .data(ResponseResult.success()) |
| | | .build()); |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.dji.sample.component.mqtt.model.CommonTopicResponse; |
| | | import com.dji.sample.component.websocket.service.ISendMessageService; |
| | | import com.dji.sample.manage.model.dto.DeviceDTO; |
| | | import com.dji.sample.manage.model.dto.DeviceFirmwareUpgradeDTO; |
| | | import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver; |
| | | import com.dji.sample.manage.model.receiver.StatusGatewayReceiver; |
| | | import com.dji.sample.manage.service.IDeviceService; |
| | |
| | | return ResponseResult.success(devicesList); |
| | | } |
| | | |
| | | /** |
| | | * Handle osd topic messages. |
| | | * @param message |
| | | */ |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_OSD) |
| | | public void osdRealTime(Message<?> message) { |
| | | String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString(); |
| | |
| | | deviceService.handleOSD(topic, payload); |
| | | } |
| | | |
| | | /** |
| | | * Receive the reported firmware version data. |
| | | * @param receiver |
| | | */ |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_FIRMWARE_VERSION) |
| | | public void updateFirmwareVersion(FirmwareVersionReceiver receiver) { |
| | | deviceService.updateFirmwareVersion(receiver); |
| | | } |
| | | |
| | | /** |
| | | * After binding the device to the workspace, the device data can only be seen on the web. |
| | | * @param device |
| | | * @param deviceSn |
| | | * @return |
| | | */ |
| | | @PostMapping("/{device_sn}/binding") |
| | | public ResponseResult bindDevice(@RequestBody DeviceDTO device, @PathVariable("device_sn") String deviceSn) { |
| | | device.setDeviceSn(deviceSn); |
| | |
| | | return isUpd ? ResponseResult.success() : ResponseResult.error(); |
| | | } |
| | | |
| | | /** |
| | | * Obtain device information according to device sn. |
| | | * @param workspaceId |
| | | * @param deviceSn |
| | | * @return |
| | | */ |
| | | @GetMapping("/{workspace_id}/devices/{device_sn}") |
| | | public ResponseResult getDevice(@PathVariable("workspace_id") String workspaceId, |
| | | @PathVariable("device_sn") String deviceSn) { |
| | |
| | | return ResponseResult.success(devices); |
| | | } |
| | | |
| | | /** |
| | | * Removing the binding state of the device. |
| | | * @param deviceSn |
| | | * @return |
| | | */ |
| | | @DeleteMapping("/{device_sn}/unbinding") |
| | | public ResponseResult unbindingDevice(@PathVariable("device_sn") String deviceSn) { |
| | | deviceService.unbindDevice(deviceSn); |
| | | return ResponseResult.success(); |
| | | } |
| | | |
| | | /** |
| | | * Update device information. |
| | | * @param device |
| | | * @param workspaceId |
| | | * @param deviceSn |
| | | * @return |
| | | */ |
| | | @PutMapping("/{workspace_id}/devices/{device_sn}") |
| | | public ResponseResult updateDevice(@RequestBody DeviceDTO device, |
| | | @PathVariable("workspace_id") String workspaceId, |
| | |
| | | boolean isUpd = deviceService.updateDevice(device); |
| | | return isUpd ? ResponseResult.success() : ResponseResult.error(); |
| | | } |
| | | |
| | | /** |
| | | * Delivers offline firmware upgrade tasks. |
| | | * @param workspaceId |
| | | * @param upgradeDTOS |
| | | * @return |
| | | */ |
| | | @PostMapping("/{workspace_id}/devices/ota") |
| | | public ResponseResult createOtaJob(@PathVariable("workspace_id") String workspaceId, |
| | | @RequestBody List<DeviceFirmwareUpgradeDTO> upgradeDTOS) { |
| | | return deviceService.createDeviceOtaJob(workspaceId, upgradeDTOS); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.controller; |
| | | |
| | | import com.dji.sample.common.model.ResponseResult; |
| | | import com.dji.sample.manage.model.dto.DeviceFirmwareNoteDTO; |
| | | import com.dji.sample.manage.service.IDeviceFirmwareService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/8/16 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("${url.manage.prefix}${url.manage.version}/workspaces") |
| | | public class DeviceFirmwareController { |
| | | |
| | | @Autowired |
| | | private IDeviceFirmwareService service; |
| | | |
| | | /** |
| | | * Get the latest firmware version information for this device model. |
| | | * @param deviceNames |
| | | * @return |
| | | */ |
| | | @GetMapping("/firmware-release-notes/latest") |
| | | public ResponseResult<List<DeviceFirmwareNoteDTO>> getLatestFirmwareNote(@RequestParam("device_name") List<String> deviceNames) { |
| | | List<DeviceFirmwareNoteDTO> releaseNotes = new ArrayList<>(); |
| | | deviceNames.forEach(deviceName -> { |
| | | Optional<DeviceFirmwareNoteDTO> latestFirmware = service.getLatestFirmwareReleaseNote(deviceName); |
| | | latestFirmware.ifPresent(releaseNotes::add); |
| | | }); |
| | | return ResponseResult.success(releaseNotes); |
| | | } |
| | | |
| | | } |
| | |
| | | @Autowired |
| | | private IDeviceHmsService deviceHmsService; |
| | | |
| | | /** |
| | | * Page to query the hms information of the device. |
| | | * @param param |
| | | * @param workspaceId |
| | | * @return |
| | | */ |
| | | @GetMapping("/{workspace_id}/devices/hms") |
| | | public ResponseResult<PaginationData<DeviceHmsDTO>> getBoundDevicesWithDomain(DeviceHmsQueryParam param, |
| | | public ResponseResult<PaginationData<DeviceHmsDTO>> getHmsInformation(DeviceHmsQueryParam param, |
| | | @PathVariable("workspace_id") String workspaceId) { |
| | | PaginationData<DeviceHmsDTO> devices = deviceHmsService.getDeviceHmsByParam(param); |
| | | |
| | | return ResponseResult.success(devices); |
| | | } |
| | | |
| | | /** |
| | | * Update unread hms messages to read status. |
| | | * @param deviceSn |
| | | * @return |
| | | */ |
| | | @PutMapping("/{workspace_id}/devices/hms/{device_sn}") |
| | | public ResponseResult updateReadHmsByDeviceSn(@PathVariable("device_sn") String deviceSn) { |
| | | deviceHmsService.updateUnreadHms(deviceSn); |
| | | return ResponseResult.success(); |
| | | } |
| | | |
| | | /** |
| | | * Get hms messages for a single device. |
| | | * @param deviceSn |
| | | * @return |
| | | */ |
| | | @GetMapping("/{workspace_id}/devices/hms/{device_sn}") |
| | | public ResponseResult<List<DeviceHmsDTO>> getUnreadHmsByDeviceSn(@PathVariable("device_sn") String deviceSn) { |
| | | PaginationData<DeviceHmsDTO> paginationData = deviceHmsService.getDeviceHmsByParam( |
| New file |
| | |
| | | package com.dji.sample.manage.controller; |
| | | |
| | | import com.dji.sample.common.model.CustomClaim; |
| | | import com.dji.sample.common.model.PaginationData; |
| | | import com.dji.sample.common.model.ResponseResult; |
| | | import com.dji.sample.manage.model.dto.DeviceLogsDTO; |
| | | import com.dji.sample.manage.model.param.DeviceLogsCreateParam; |
| | | import com.dji.sample.manage.model.param.DeviceLogsQueryParam; |
| | | import com.dji.sample.manage.model.param.LogsFileUpdateParam; |
| | | import com.dji.sample.manage.service.IDeviceLogsService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.net.URL; |
| | | import java.util.List; |
| | | |
| | | import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | @RestController |
| | | @Slf4j |
| | | @RequestMapping("${url.manage.prefix}${url.manage.version}/workspaces") |
| | | public class DeviceLogsController { |
| | | |
| | | @Autowired |
| | | private IDeviceLogsService deviceLogsService; |
| | | |
| | | /** |
| | | * Obtain the device upload log list by paging according to the query parameters. |
| | | * @param workspaceId |
| | | * @param deviceSn |
| | | * @param param |
| | | * @return |
| | | */ |
| | | @GetMapping("/{workspace_id}/devices/{device_sn}/logs-uploaded") |
| | | public ResponseResult getUploadedLogs(DeviceLogsQueryParam param, @PathVariable("workspace_id") String workspaceId, |
| | | @PathVariable("device_sn") String deviceSn) { |
| | | PaginationData<DeviceLogsDTO> data = deviceLogsService.getUploadedLogs(deviceSn, param); |
| | | return ResponseResult.success(data); |
| | | } |
| | | |
| | | /** |
| | | * Get a list of log files that can be uploaded in real time. |
| | | * @param workspaceId |
| | | * @param deviceSn |
| | | * @param domainList |
| | | * @return |
| | | */ |
| | | @GetMapping("/{workspace_id}/devices/{device_sn}/logs") |
| | | public ResponseResult getLogsBySn(@PathVariable("workspace_id") String workspaceId, |
| | | @PathVariable("device_sn") String deviceSn, |
| | | @RequestParam("domain_list") List<String> domainList) { |
| | | return deviceLogsService.getRealTimeLogs(deviceSn, domainList); |
| | | } |
| | | |
| | | /** |
| | | * Initiate a log upload request to the gateway. |
| | | * @return |
| | | */ |
| | | @PostMapping("/{workspace_id}/devices/{device_sn}/logs") |
| | | public ResponseResult uploadLogs(@PathVariable("workspace_id") String workspaceId, |
| | | @PathVariable("device_sn") String deviceSn, |
| | | HttpServletRequest request, @RequestBody DeviceLogsCreateParam param) { |
| | | |
| | | CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM); |
| | | |
| | | return deviceLogsService.pushFileUpload(customClaim.getUsername(), deviceSn, param); |
| | | } |
| | | |
| | | /** |
| | | * Cancel logs file upload. |
| | | * @return |
| | | */ |
| | | @DeleteMapping("/{workspace_id}/devices/{device_sn}/logs") |
| | | public ResponseResult cancelUploadedLogs(@PathVariable("workspace_id") String workspaceId, |
| | | @PathVariable("device_sn") String deviceSn, |
| | | @RequestBody LogsFileUpdateParam param) { |
| | | |
| | | return deviceLogsService.pushUpdateFile(deviceSn, param); |
| | | } |
| | | |
| | | /** |
| | | * Delete upload history. |
| | | * @return |
| | | */ |
| | | @DeleteMapping("/{workspace_id}/devices/{device_sn}/logs/{logs_id}") |
| | | public ResponseResult deleteUploadedLogs(@PathVariable("workspace_id") String workspaceId, |
| | | @PathVariable("device_sn") String deviceSn, |
| | | @PathVariable("logs_id") String logsId) { |
| | | deviceLogsService.deleteLogs(deviceSn, logsId); |
| | | return ResponseResult.success(); |
| | | } |
| | | /** |
| | | * Query the download address of the file according to the wayline file id, |
| | | * and redirect to this address directly for download. |
| | | * @param workspaceId |
| | | * @param fileId |
| | | * @param logsId |
| | | * @param response |
| | | */ |
| | | @GetMapping("/{workspace_id}/logs/{logs_id}/url/{file_id}") |
| | | public ResponseResult getFileUrl(@PathVariable(name = "workspace_id") String workspaceId, |
| | | @PathVariable(name = "file_id") String fileId, |
| | | @PathVariable(name = "logs_id") String logsId, HttpServletResponse response) { |
| | | |
| | | try { |
| | | URL url = deviceLogsService.getLogsFileUrl(logsId, fileId); |
| | | return ResponseResult.success(url.toString()); |
| | | } catch (Exception e) { |
| | | log.error("Failed to get the logs file download address."); |
| | | e.printStackTrace(); |
| | | } |
| | | return ResponseResult.error("Failed to get the logs file download address."); |
| | | } |
| | | } |
| | |
| | | import com.dji.sample.component.mqtt.model.ChannelName; |
| | | import com.dji.sample.manage.model.receiver.DeviceBasicReceiver; |
| | | import com.dji.sample.manage.service.IDevicePayloadService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.integration.annotation.ServiceActivator; |
| | | import org.springframework.messaging.MessageHeaders; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author sean.zhou |
| | |
| | | * @version 0.1 |
| | | */ |
| | | @RestController |
| | | @Slf4j |
| | | public class DevicePayloadController { |
| | | |
| | | @Autowired |
| | |
| | | * Note: Only the data of the drone payload is handled here. You can handle other data from the drone |
| | | * according to your business needs. |
| | | * @param deviceBasic basic drone data |
| | | * @return drone's sn |
| | | * @param headers |
| | | */ |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_BASIC) |
| | | public void stateBasic(DeviceBasicReceiver deviceBasic) { |
| | | // Delete all payload information for the drone based on the drone's sn. |
| | | devicePayloadService.deletePayloadsByDeviceSn(List.of(deviceBasic.getDeviceSn())); |
| | | public void stateBasic(DeviceBasicReceiver deviceBasic, MessageHeaders headers) { |
| | | |
| | | // Save the new payload information. |
| | | boolean isSave = devicePayloadService.savePayloadDTOs(deviceBasic.getPayloads()); |
| | | |
| | | log.debug("The result of saving the payloads is {}.", isSave); |
| | | |
| | | devicePayloadService.saveDeviceBasicPayload(deviceBasic.getPayloads(), headers.getTimestamp()); |
| | | } |
| | | } |
| | |
| | | |
| | | import com.dji.sample.common.model.CustomClaim; |
| | | import com.dji.sample.common.model.ResponseResult; |
| | | import com.dji.sample.component.mqtt.model.Chan; |
| | | import com.dji.sample.component.mqtt.model.ChannelName; |
| | | import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
| | | import com.dji.sample.component.mqtt.model.ServiceReply; |
| | | import com.dji.sample.manage.model.dto.CapacityDeviceDTO; |
| | | import com.dji.sample.manage.model.dto.LiveTypeDTO; |
| | | import com.dji.sample.manage.model.receiver.LiveCapacityReceiver; |
| | | import com.dji.sample.manage.service.ILiveStreamService; |
| | | import com.fasterxml.jackson.core.type.TypeReference; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.integration.annotation.ServiceActivator; |
| | | import org.springframework.messaging.Message; |
| | | import org.springframework.messaging.MessageHeaders; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.io.IOException; |
| | | import java.util.List; |
| | | |
| | | import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM; |
| | |
| | | * @param liveCapacity the capacity of drone and dock |
| | | */ |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_CAPACITY) |
| | | public void stateCapacity(LiveCapacityReceiver liveCapacity) { |
| | | liveStreamService.saveLiveCapacity(liveCapacity); |
| | | public void stateCapacity(LiveCapacityReceiver liveCapacity, MessageHeaders headers) { |
| | | liveStreamService.saveLiveCapacity(liveCapacity, headers.getTimestamp()); |
| | | } |
| | | |
| | | /** |
| | |
| | | return liveStreamService.liveSetQuality(liveParam); |
| | | } |
| | | |
| | | /** |
| | | * Handle the reply message from the pilot side to the on-demand video. |
| | | * @param message reply message |
| | | * @throws IOException |
| | | */ |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_SERVICE_REPLY) |
| | | public void serviceReply(Message<?> message) throws IOException { |
| | | byte[] payload = (byte[])message.getPayload(); |
| | | CommonTopicReceiver<ServiceReply> receiver = mapper.readValue(payload, |
| | | new TypeReference<CommonTopicReceiver<ServiceReply>>() { |
| | | }); |
| | | Chan<CommonTopicReceiver> chan = Chan.getInstance(); |
| | | // Put the message to the chan object. |
| | | chan.put(receiver); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.dao; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.dji.sample.manage.model.entity.DeviceFirmwareEntity; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/8/16 |
| | | */ |
| | | public interface IDeviceFirmwareMapper extends BaseMapper<DeviceFirmwareEntity> { |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.dao; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.dji.sample.manage.model.entity.DeviceLogsEntity; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | public interface IDeviceLogsMapper extends BaseMapper<DeviceLogsEntity> { |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.dao; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.dji.sample.manage.model.entity.LogsFileIndexEntity; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/8 |
| | | */ |
| | | public interface ILogsFileIndexMapper extends BaseMapper<LogsFileIndexEntity> { |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.dao; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.dji.sample.manage.model.entity.LogsFileEntity; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | public interface ILogsFileMapper extends BaseMapper<LogsFileEntity> { |
| | | } |
| | |
| | | } |
| | | |
| | | public static HmsMessage get(String key) { |
| | | if (nodes.get(key) == null) { |
| | | return new HmsMessage(); |
| | | } |
| | | return mapper.convertValue(nodes.get(key), HmsMessage.class); |
| | | } |
| | | } |
| | |
| | | private String workspaceName; |
| | | |
| | | private DeviceDTO children; |
| | | |
| | | private Integer firmwareStatus; |
| | | |
| | | private Integer firmwareProgress; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.dto; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.time.LocalDate; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/8/16 |
| | | */ |
| | | @Builder |
| | | @Data |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class DeviceFirmwareDTO { |
| | | |
| | | private String firmwareId; |
| | | |
| | | private String fileName; |
| | | |
| | | private String productVersion; |
| | | |
| | | private String fileUrl; |
| | | |
| | | private Long fileSize; |
| | | |
| | | private String fileMd5; |
| | | |
| | | private String deviceName; |
| | | |
| | | private String releaseNote; |
| | | |
| | | private LocalDate releasedTime; |
| | | |
| | | private Boolean firmwareStatus; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.dto; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.time.LocalDate; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/8/16 |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class DeviceFirmwareNoteDTO { |
| | | |
| | | private String deviceName; |
| | | |
| | | private String productVersion; |
| | | |
| | | private String releaseNote; |
| | | |
| | | private LocalDate releasedTime; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/8/16 |
| | | */ |
| | | @Data |
| | | public class DeviceFirmwareUpgradeDTO { |
| | | |
| | | private String deviceName; |
| | | |
| | | private String sn; |
| | | |
| | | private String productVersion; |
| | | |
| | | private Integer firmwareUpgradeType; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.dto; |
| | | |
| | | import com.dji.sample.manage.model.receiver.LogsFileUploadList; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class DeviceLogsDTO { |
| | | |
| | | private String logsId; |
| | | |
| | | private LocalDateTime happenTime; |
| | | |
| | | private String userName; |
| | | |
| | | private String logsInformation; |
| | | |
| | | private LocalDateTime createTime; |
| | | |
| | | private Integer status; |
| | | |
| | | private TopologyDTO deviceTopo; |
| | | |
| | | private List<LogsProgressDTO> logsProgress; |
| | | |
| | | private LogsFileUploadList deviceLogs; |
| | | |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.dto; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/9 |
| | | */ |
| | | @Builder |
| | | @Data |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class LogsFileDTO { |
| | | |
| | | private String fileId; |
| | | |
| | | private String name; |
| | | |
| | | private Long size; |
| | | |
| | | private String logsId; |
| | | |
| | | private String deviceSn; |
| | | |
| | | private String fingerprint; |
| | | |
| | | private String objectKey; |
| | | |
| | | private Boolean status; |
| | | |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.dto; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/9 |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class LogsOutputProgressDTO { |
| | | |
| | | private String logsId; |
| | | |
| | | private String status; |
| | | |
| | | private List<LogsProgressDTO> files; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.dto; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class LogsProgressDTO { |
| | | |
| | | private String deviceSn; |
| | | |
| | | private String deviceModelDomain; |
| | | |
| | | private Integer progress; |
| | | |
| | | private Integer result; |
| | | |
| | | private Float uploadRate; |
| | | |
| | | private String status; |
| | | |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.dto; |
| | | |
| | | import com.dji.sample.manage.model.receiver.LogsFileUploadList; |
| | | import com.dji.sample.media.model.CredentialsDTO; |
| | | import com.dji.sample.media.model.StsCredentialsDTO; |
| | | import com.fasterxml.jackson.annotation.JsonProperty; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/8 |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class LogsUploadCredentialsDTO { |
| | | |
| | | private String bucket; |
| | | |
| | | private CredentialsDTO credentials; |
| | | |
| | | private String endpoint; |
| | | |
| | | @JsonProperty("file_store_dir") |
| | | private String objectKeyPrefix; |
| | | |
| | | private String provider; |
| | | |
| | | private String fileType = "text_log"; |
| | | |
| | | private LogsFileUploadList params; |
| | | |
| | | public LogsUploadCredentialsDTO(StsCredentialsDTO sts) { |
| | | this.bucket = sts.getBucket(); |
| | | Long expire = sts.getCredentials().getExpire(); |
| | | sts.getCredentials().setExpire(System.currentTimeMillis() + (expire - 60) * 1000); |
| | | this.credentials = sts.getCredentials(); |
| | | this.endpoint = sts.getEndpoint(); |
| | | this.objectKeyPrefix = sts.getObjectKeyPrefix(); |
| | | this.provider = sts.getProvider(); |
| | | } |
| | | } |
| | |
| | | @TableField(value = "firmware_version") |
| | | private String firmwareVersion; |
| | | |
| | | @TableField(value = "compatible_status") |
| | | private Boolean compatibleStatus; |
| | | |
| | | @TableField(value = "bound_status") |
| | | private Boolean boundStatus; |
| | | |
| New file |
| | |
| | | package com.dji.sample.manage.model.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.*; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/8/16 |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | @TableName("manage_device_firmware") |
| | | public class DeviceFirmwareEntity implements Serializable { |
| | | |
| | | private static final long serialVersionUID = -12L; |
| | | |
| | | @TableId(type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | @TableField("firmware_id") |
| | | private String firmwareId; |
| | | |
| | | @TableField("file_name") |
| | | private String fileName; |
| | | |
| | | @TableField("firmware_version") |
| | | private String firmwareVersion; |
| | | |
| | | @TableField("file_url") |
| | | private String fileUrl; |
| | | |
| | | @TableField("file_size") |
| | | private Long fileSize; |
| | | |
| | | @TableField("file_md5") |
| | | private String fileMd5; |
| | | |
| | | @TableField("device_name") |
| | | private String deviceName; |
| | | |
| | | @TableField("release_note") |
| | | private String releaseNote; |
| | | |
| | | @TableField("release_date") |
| | | private Long releaseDate; |
| | | |
| | | @TableField("status") |
| | | private Boolean status; |
| | | |
| | | @TableField(value = "create_time", fill = FieldFill.INSERT) |
| | | private Long createTime; |
| | | |
| | | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) |
| | | private Long updateTime; |
| | | |
| | | } |
| | |
| | | @TableName(value = "manage_device_hms") |
| | | public class DeviceHmsEntity implements Serializable, Cloneable { |
| | | |
| | | private static final long serialVersionUID = -12L; |
| | | |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| New file |
| | |
| | | package com.dji.sample.manage.model.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.*; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | @TableName("manage_device_logs") |
| | | @Data |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | @Builder |
| | | public class DeviceLogsEntity implements Serializable { |
| | | |
| | | private static final long serialVersionUID = -12L; |
| | | |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | @TableField("logs_id") |
| | | private String logsId; |
| | | |
| | | @TableField("username") |
| | | private String username; |
| | | |
| | | @TableField("logs_info") |
| | | private String logsInfo; |
| | | |
| | | @TableField("device_sn") |
| | | private String deviceSn; |
| | | |
| | | @TableField("happen_time") |
| | | private Long happenTime; |
| | | |
| | | @TableField("status") |
| | | private Integer status; |
| | | |
| | | @TableField(value = "create_time", fill = FieldFill.INSERT) |
| | | private Long createTime; |
| | | |
| | | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) |
| | | private Long updateTime; |
| | | |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.*; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | @TableName("logs_file") |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class LogsFileEntity implements Serializable { |
| | | |
| | | private static final long serialVersionUID = -12L; |
| | | |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | @TableField("file_id") |
| | | private String fileId; |
| | | |
| | | @TableField("name") |
| | | private String name; |
| | | |
| | | @TableField("size") |
| | | private Long size; |
| | | |
| | | @TableField("logs_id") |
| | | private String logsId; |
| | | |
| | | @TableField("device_sn") |
| | | private String deviceSn; |
| | | |
| | | @TableField("fingerprint") |
| | | private String fingerprint; |
| | | |
| | | @TableField("object_key") |
| | | private String objectKey; |
| | | |
| | | @TableField("status") |
| | | private Boolean status; |
| | | |
| | | @TableField(value = "create_time", fill = FieldFill.INSERT) |
| | | private Long createTime; |
| | | |
| | | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) |
| | | private Long updateTime; |
| | | |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.*; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/8 |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | @TableName("logs_file_index") |
| | | public class LogsFileIndexEntity implements Serializable { |
| | | |
| | | private static final long serialVersionUID = -12L; |
| | | |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | @TableField("boot_index") |
| | | private Integer bootIndex; |
| | | |
| | | @TableField("file_id") |
| | | private String fileId; |
| | | |
| | | @TableField("start_time") |
| | | private Long startTime; |
| | | |
| | | @TableField("end_time") |
| | | private Long endTime; |
| | | |
| | | @TableField("size") |
| | | private Long size; |
| | | |
| | | @TableField("device_sn") |
| | | private String deviceSn; |
| | | |
| | | @TableField("domain") |
| | | private Integer domain; |
| | | |
| | | @TableField(value = "create_time", fill = FieldFill.INSERT) |
| | | private Long createTime; |
| | | |
| | | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) |
| | | private Long updateTime; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.enums; |
| | | |
| | | import lombok.Getter; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/8/15 |
| | | */ |
| | | @Getter |
| | | public enum DeviceFirmwareStatusEnum { |
| | | |
| | | /** |
| | | * no need to upgrade |
| | | */ |
| | | NOT_UPGRADE(1), |
| | | |
| | | /** |
| | | * to upgraded |
| | | */ |
| | | NORMAL_UPGRADE(2), |
| | | |
| | | /** |
| | | * A consistency upgrade is required. |
| | | */ |
| | | CONSISTENT_UPGRADE(3), |
| | | |
| | | /** |
| | | * during upgrade |
| | | */ |
| | | UPGRADING(4), |
| | | |
| | | UNKNOWN(-1); |
| | | |
| | | int val; |
| | | |
| | | DeviceFirmwareStatusEnum(int val) { |
| | | this.val = val; |
| | | } |
| | | |
| | | public static DeviceFirmwareStatusEnum find(int val) { |
| | | return Arrays.stream(DeviceFirmwareStatusEnum.values()) |
| | | .filter(firmwareStatus -> firmwareStatus.val == val) |
| | | .findFirst().orElse(UNKNOWN); |
| | | } |
| | | |
| | | @Getter |
| | | public enum CompatibleStatusEnum { |
| | | INCONSISTENT(1), |
| | | |
| | | CONSISTENT(0); |
| | | |
| | | int val; |
| | | |
| | | CompatibleStatusEnum(int val) { |
| | | this.val = val; |
| | | } |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.enums; |
| | | |
| | | import com.dji.sample.component.mqtt.model.EventsResultStatusEnum; |
| | | import lombok.Getter; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.Collections; |
| | | import java.util.HashSet; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/8 |
| | | */ |
| | | @Getter |
| | | public enum DeviceLogsStatusEnum { |
| | | |
| | | UPLOADING(1, EventsResultStatusEnum.IN_PROGRESS), |
| | | |
| | | DONE(2, EventsResultStatusEnum.OK), |
| | | |
| | | CANCELED(3, EventsResultStatusEnum.CANCELED), |
| | | |
| | | FAILED(4, EventsResultStatusEnum.FAILED, EventsResultStatusEnum.REJECTED, EventsResultStatusEnum.TIMEOUT), |
| | | |
| | | UNKNOWN(-1); |
| | | |
| | | int val; |
| | | |
| | | HashSet<EventsResultStatusEnum> status; |
| | | |
| | | DeviceLogsStatusEnum(int val, EventsResultStatusEnum... status) { |
| | | this.status = new HashSet<>(); |
| | | Collections.addAll(this.status, status); |
| | | this.val = val; |
| | | } |
| | | |
| | | public static DeviceLogsStatusEnum find(EventsResultStatusEnum status) { |
| | | return Arrays.stream(DeviceLogsStatusEnum.values()).filter(element -> element.status.contains(status)).findAny().orElse(UNKNOWN); |
| | | } |
| | | } |
| | |
| | | @Getter |
| | | public enum HmsFaqIdEnum { |
| | | |
| | | DOCK_TIP("dock_tip_"), |
| | | |
| | | FPV_TIP("fpv_tip_"); |
| | | |
| | | private String text; |
| | |
| | | .orElse(UNKNOWN); |
| | | } |
| | | } |
| | | |
| | | @Getter |
| | | public enum FormatKeyEnum { |
| | | |
| | | ALARM_ID("alarmid", 0), |
| | | |
| | | COMPONENT_INDEX("component_index", 1), |
| | | |
| | | INDEX("index", 2), |
| | | |
| | | BATTERY_INDEX("battery_index", 3), |
| | | |
| | | DOCK_COVER_INDEX("dock_cover_index", 4), |
| | | |
| | | CHARGING_ROD_INDEX("charging_rod_index", 5), |
| | | |
| | | UNKNOWN("unknown", -1); |
| | | |
| | | public static final char KEY_START = '%'; |
| | | |
| | | String key; |
| | | int index; |
| | | |
| | | FormatKeyEnum(String key, int index) { |
| | | this.key = key; |
| | | this.index = index; |
| | | } |
| | | |
| | | public static FormatKeyEnum find(String key) { |
| | | return Arrays.stream(FormatKeyEnum.values()) |
| | | .filter(format -> format.getKey().equals(key)) |
| | | .findAny().orElse(UNKNOWN); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.enums; |
| | | |
| | | import lombok.Getter; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/9 |
| | | */ |
| | | @Getter |
| | | public enum LogsFileUpdateMethodEnum { |
| | | |
| | | CANCEL("cancel"), |
| | | |
| | | UNKNOWN("unknown"); |
| | | |
| | | String method; |
| | | |
| | | LogsFileUpdateMethodEnum(String method) { |
| | | this.method = method; |
| | | } |
| | | |
| | | public static LogsFileUpdateMethodEnum find(String method) { |
| | | return Arrays.stream(LogsFileUpdateMethodEnum.values()).filter(e -> e.method.equals(method)).findAny().orElse(UNKNOWN); |
| | | } |
| | | } |
| | |
| | | package com.dji.sample.manage.model.param; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonProperty; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class DeviceHmsQueryParam implements Serializable { |
| | | public class DeviceHmsQueryParam { |
| | | |
| | | @JsonProperty("device_sn") |
| | | private Set<String> deviceSn; |
| | | |
| | | @JsonProperty("begin_time") |
| | | private Long beginTime; |
| | | |
| | | @JsonProperty("end_time") |
| | | private Long endTime; |
| | | |
| | | private String language; |
| | |
| | | |
| | | private Long page; |
| | | |
| | | @JsonProperty("page_size") |
| | | private Long pageSize; |
| | | |
| | | private Integer level; |
| | | |
| | | @JsonProperty("update_time") |
| | | private Long updateTime; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.param; |
| | | |
| | | import com.dji.sample.manage.model.receiver.LogsFileUpload; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/8 |
| | | */ |
| | | @Data |
| | | public class DeviceLogsCreateParam { |
| | | |
| | | private String logsInformation; |
| | | |
| | | private Long happenTime; |
| | | |
| | | private List<LogsFileUpload> files; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.param; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | @Data |
| | | public class DeviceLogsQueryParam { |
| | | |
| | | private Long page; |
| | | |
| | | private Long pageSize; |
| | | |
| | | private Integer status; |
| | | |
| | | private Long beginTime; |
| | | |
| | | private Long endTime; |
| | | |
| | | private String logsInformation; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.param; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/8/16 |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class DeviceOtaCreateParam { |
| | | |
| | | private String sn; |
| | | |
| | | private String productVersion; |
| | | |
| | | private String fileUrl; |
| | | |
| | | private String md5; |
| | | |
| | | private Long fileSize; |
| | | |
| | | private Integer firmwareUpgradeType; |
| | | |
| | | private String fileName; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.param; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/9 |
| | | */ |
| | | @Data |
| | | public class LogsFileUpdateParam { |
| | | |
| | | private String status; |
| | | |
| | | @JsonProperty("module_list") |
| | | private List<String> deviceModelDomainList; |
| | | |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.receiver; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/9 |
| | | */ |
| | | @Data |
| | | public class LogsExtFileReceiver { |
| | | |
| | | @JsonProperty("module") |
| | | private String deviceModelDomain; |
| | | |
| | | private Long size; |
| | | |
| | | private String deviceSn; |
| | | |
| | | private String key; |
| | | |
| | | private String fingerprint; |
| | | |
| | | private LogsProgressReceiver progress; |
| | | |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.receiver; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class LogsFile { |
| | | |
| | | private Integer bootIndex; |
| | | |
| | | private Long endTime; |
| | | |
| | | private Long startTime; |
| | | |
| | | private Long size; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.receiver; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonProperty; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | @Data |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | @Builder |
| | | public class LogsFileUpload { |
| | | |
| | | private String deviceSn; |
| | | |
| | | private List<LogsFile> list; |
| | | |
| | | @JsonProperty("module") |
| | | private String deviceModelDomain; |
| | | |
| | | private String objectKey; |
| | | |
| | | private Integer result; |
| | | |
| | | private String fileId; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.receiver; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class LogsFileUploadList { |
| | | |
| | | private List<LogsFileUpload> files; |
| | | |
| | | private Integer result; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.receiver; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/9 |
| | | */ |
| | | @Data |
| | | public class LogsProgressReceiver { |
| | | |
| | | private Integer currentStep; |
| | | |
| | | private Integer totalStep; |
| | | |
| | | private Integer progress; |
| | | |
| | | private Long finishTime; |
| | | |
| | | private Float uploadRate; |
| | | |
| | | private String status; |
| | | |
| | | private Integer result; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.receiver; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/9 |
| | | */ |
| | | @Data |
| | | public class OutputLogsExtReceiver { |
| | | |
| | | private List<LogsExtFileReceiver> files; |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.model.receiver; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/9 |
| | | */ |
| | | @Data |
| | | public class OutputLogsProgressReceiver { |
| | | |
| | | private OutputLogsExtReceiver ext; |
| | | |
| | | private String status; |
| | | } |
| | |
| | | * Save the live capability data of the device. |
| | | * @param capacityCameraReceivers |
| | | * @param deviceSn |
| | | * @param timestamp |
| | | */ |
| | | void saveCapacityCameraReceiverList(List<CapacityCameraReceiver> capacityCameraReceivers, String deviceSn); |
| | | void saveCapacityCameraReceiverList(List<CapacityCameraReceiver> capacityCameraReceivers, String deviceSn, Long timestamp); |
| | | |
| | | /** |
| | | * Convert the received camera capability object into camera data transfer object. |
| New file |
| | |
| | | package com.dji.sample.manage.service; |
| | | |
| | | import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
| | | import com.dji.sample.manage.model.dto.DeviceFirmwareDTO; |
| | | import com.dji.sample.manage.model.dto.DeviceFirmwareNoteDTO; |
| | | import com.dji.sample.manage.model.dto.DeviceFirmwareUpgradeDTO; |
| | | import com.dji.sample.manage.model.param.DeviceOtaCreateParam; |
| | | import org.springframework.messaging.MessageHeaders; |
| | | |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/8/16 |
| | | */ |
| | | public interface IDeviceFirmwareService { |
| | | |
| | | /** |
| | | * Query specific firmware information based on the device model and firmware version. |
| | | * @param deviceName |
| | | * @param version |
| | | * @return |
| | | */ |
| | | Optional<DeviceFirmwareDTO> getFirmware(String deviceName, String version); |
| | | |
| | | /** |
| | | * Get the latest firmware release note for this device model. |
| | | * @param deviceName |
| | | * @return |
| | | */ |
| | | Optional<DeviceFirmwareNoteDTO> getLatestFirmwareReleaseNote(String deviceName); |
| | | |
| | | /** |
| | | * Get the firmware information that the device needs to update. |
| | | * @param upgradeDTOS |
| | | * @return |
| | | */ |
| | | List<DeviceOtaCreateParam> getDeviceOtaFirmware(List<DeviceFirmwareUpgradeDTO> upgradeDTOS); |
| | | |
| | | /** |
| | | * Interface to handle device firmware update progress. |
| | | * @param receiver |
| | | * @param headers |
| | | */ |
| | | void handleOtaProgress(CommonTopicReceiver receiver, MessageHeaders headers); |
| | | } |
| | |
| | | */ |
| | | public interface IDeviceHmsService { |
| | | |
| | | /** |
| | | * Handle hms messages. |
| | | * @param receiver |
| | | * @param headers |
| | | */ |
| | | void handleHms(CommonTopicReceiver receiver, MessageHeaders headers); |
| | | |
| | | /** |
| | | * Query hms data by paging according to query parameters. |
| | | * @param param |
| | | * @return |
| | | */ |
| | | PaginationData<DeviceHmsDTO> getDeviceHmsByParam(DeviceHmsQueryParam param); |
| | | |
| | | /** |
| | | * Read message handling. |
| | | * @param deviceSn |
| | | */ |
| | | void updateUnreadHms(String deviceSn); |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.service; |
| | | |
| | | import com.dji.sample.common.model.PaginationData; |
| | | import com.dji.sample.common.model.ResponseResult; |
| | | import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
| | | import com.dji.sample.manage.model.dto.DeviceLogsDTO; |
| | | import com.dji.sample.manage.model.param.DeviceLogsCreateParam; |
| | | import com.dji.sample.manage.model.param.DeviceLogsQueryParam; |
| | | import com.dji.sample.manage.model.param.LogsFileUpdateParam; |
| | | import org.springframework.messaging.MessageHeaders; |
| | | |
| | | import java.net.URL; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | public interface IDeviceLogsService { |
| | | |
| | | /** |
| | | * Obtain the device upload log list by paging according to the query parameters. |
| | | * @param deviceSn |
| | | * @param param |
| | | * @return |
| | | */ |
| | | PaginationData<DeviceLogsDTO> getUploadedLogs(String deviceSn, DeviceLogsQueryParam param); |
| | | |
| | | /** |
| | | * Get a list of log files that can be uploaded in real time. |
| | | * @param deviceSn |
| | | * @param domainList |
| | | * @return |
| | | */ |
| | | ResponseResult getRealTimeLogs(String deviceSn, List<String> domainList); |
| | | |
| | | /** |
| | | * Add device logs. |
| | | * |
| | | * @param bid |
| | | * @param username |
| | | * @param deviceSn |
| | | * @param param |
| | | * @return logs id |
| | | */ |
| | | String insertDeviceLogs(String bid, String username, String deviceSn, DeviceLogsCreateParam param); |
| | | |
| | | /** |
| | | * Initiate a log upload request to the gateway. |
| | | * @param username |
| | | * @param deviceSn |
| | | * @param param |
| | | * @return |
| | | */ |
| | | ResponseResult pushFileUpload(String username, String deviceSn, DeviceLogsCreateParam param); |
| | | |
| | | /** |
| | | * Push a request to modify the status of the logs file. |
| | | * @param deviceSn |
| | | * @param param |
| | | * @return |
| | | */ |
| | | ResponseResult pushUpdateFile(String deviceSn, LogsFileUpdateParam param); |
| | | |
| | | /** |
| | | * Delete log records. |
| | | * @param deviceSn |
| | | * @param logsId |
| | | */ |
| | | void deleteLogs(String deviceSn, String logsId); |
| | | |
| | | /** |
| | | * Handle logs file upload progress. |
| | | * @param receiver |
| | | * @param headers |
| | | */ |
| | | void handleFileUploadProgress(CommonTopicReceiver receiver, MessageHeaders headers); |
| | | |
| | | /** |
| | | * Update status, which is updated when the logs upload succeeds or fails. |
| | | * @param logsId |
| | | * @param value |
| | | */ |
| | | void updateLogsStatus(String logsId, Integer value); |
| | | |
| | | /** |
| | | * Get the file address. |
| | | * @param logsId |
| | | * @param fileId |
| | | * @return |
| | | */ |
| | | URL getLogsFileUrl(String logsId, String fileId); |
| | | } |
| | |
| | | import com.dji.sample.manage.model.receiver.DevicePayloadReceiver; |
| | | import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | * @param receiver |
| | | */ |
| | | void updateFirmwareVersion(FirmwareVersionReceiver receiver); |
| | | |
| | | /** |
| | | * Handle the topic that contains the payloads field in the state, and save the payloads data. |
| | | * @param payloadReceiverList |
| | | * @param timestamp |
| | | */ |
| | | void saveDeviceBasicPayload(List<DevicePayloadReceiver> payloadReceiverList, Long timestamp); |
| | | |
| | | /** |
| | | * Delete payload data based on payload sn. |
| | | * @param payloadSns |
| | | */ |
| | | void deletePayloadsByPayloadsSn(Collection<String> payloadSns); |
| | | } |
| | |
| | | package com.dji.sample.manage.service; |
| | | |
| | | import com.dji.sample.common.model.PaginationData; |
| | | import com.dji.sample.common.model.ResponseResult; |
| | | import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
| | | import com.dji.sample.component.mqtt.model.CommonTopicResponse; |
| | | import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession; |
| | | import com.dji.sample.manage.model.dto.DeviceDTO; |
| | | import com.dji.sample.manage.model.dto.DeviceFirmwareUpgradeDTO; |
| | | import com.dji.sample.manage.model.dto.TopologyDeviceDTO; |
| | | import com.dji.sample.manage.model.param.DeviceQueryParam; |
| | | import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver; |
| | |
| | | * @param receiver |
| | | */ |
| | | void updateFirmwareVersion(FirmwareVersionReceiver receiver); |
| | | |
| | | /** |
| | | * Create job for device firmware updates. |
| | | * @param workspaceId |
| | | * @param upgradeDTOS |
| | | * @return |
| | | */ |
| | | ResponseResult createDeviceOtaJob(String workspaceId, List<DeviceFirmwareUpgradeDTO> upgradeDTOS); |
| | | } |
| | |
| | | /** |
| | | * Save live capability data. |
| | | * @param liveCapacityReceiver |
| | | * @param timestamp |
| | | */ |
| | | void saveLiveCapacity(LiveCapacityReceiver liveCapacityReceiver); |
| | | void saveLiveCapacity(LiveCapacityReceiver liveCapacityReceiver, Long timestamp); |
| | | |
| | | /** |
| | | * Initiate a live streaming by publishing mqtt message. |
| New file |
| | |
| | | package com.dji.sample.manage.service; |
| | | |
| | | import com.dji.sample.manage.model.dto.LogsFileDTO; |
| | | import com.dji.sample.manage.model.receiver.LogsFile; |
| | | import com.dji.sample.manage.model.receiver.LogsFileUpload; |
| | | |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/8 |
| | | */ |
| | | public interface ILogsFileIndexService { |
| | | |
| | | /** |
| | | * Insert the index of the device logs. |
| | | * @param file |
| | | * @param deviceSn |
| | | * @param domain |
| | | * @param fileId |
| | | * @return |
| | | */ |
| | | Boolean insertFileIndex(LogsFile file, String deviceSn, Integer domain, String fileId); |
| | | |
| | | /** |
| | | * Query logs file upload information based on the file id. |
| | | * @param fileId |
| | | * @return |
| | | */ |
| | | Optional<LogsFileUpload> getFileIndexByFileId(String fileId); |
| | | |
| | | /** |
| | | * Batch query logs file upload information. |
| | | * @param fileIds |
| | | * @return |
| | | */ |
| | | List<LogsFileUpload> getFileIndexByFileIds(List<LogsFileDTO> fileIds); |
| | | |
| | | /** |
| | | * Delete log index data based on file id. |
| | | * @param fileIds |
| | | */ |
| | | void deleteFileIndexByFileIds(List<String> fileIds); |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.service; |
| | | |
| | | import com.dji.sample.manage.model.dto.LogsFileDTO; |
| | | import com.dji.sample.manage.model.receiver.LogsExtFileReceiver; |
| | | import com.dji.sample.manage.model.receiver.LogsFileUpload; |
| | | |
| | | import java.net.URL; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | public interface ILogsFileService { |
| | | |
| | | /** |
| | | * Query the uploaded log file information based on the log id. |
| | | * @param logsId |
| | | * @return |
| | | */ |
| | | List<LogsFileDTO> getLogsFileInfoByLogsId(String logsId); |
| | | |
| | | /** |
| | | * Query the uploaded log file structure information based on the log id. |
| | | * @param logsId |
| | | * @return |
| | | */ |
| | | List<LogsFileUpload> getLogsFileByLogsId(String logsId); |
| | | |
| | | /** |
| | | * Added logs file. |
| | | * @param file |
| | | * @param logsId |
| | | * @return |
| | | */ |
| | | Boolean insertFile(LogsFileUpload file, String logsId); |
| | | |
| | | /** |
| | | * Delete logs files. |
| | | * @param logsId |
| | | */ |
| | | void deleteFileByLogsId(String logsId); |
| | | |
| | | /** |
| | | * Update file information. |
| | | * @param logsId |
| | | * @param fileReceiver |
| | | */ |
| | | void updateFile(String logsId, LogsExtFileReceiver fileReceiver); |
| | | |
| | | /** |
| | | * Update file upload status. |
| | | * @param logsId |
| | | * @param isUploaded |
| | | */ |
| | | void updateFileUploadStatus(String logsId, Boolean isUploaded); |
| | | |
| | | /** |
| | | * Get the file address. |
| | | * @param logsId |
| | | * @param fileId |
| | | * @return |
| | | */ |
| | | URL getLogsFileUrl(String logsId, String fileId); |
| | | } |
| | |
| | | import com.dji.sample.manage.model.dto.TopologyDTO; |
| | | |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | |
| | | /** |
| | | * @author sean |
| | |
| | | * @return |
| | | */ |
| | | List<TopologyDTO> getDeviceTopology(String workspaceId); |
| | | |
| | | /** |
| | | * Query the topology according to the gateway sn. |
| | | * @param gatewaySn |
| | | * @return |
| | | */ |
| | | Optional<TopologyDTO> getDeviceTopologyByGatewaySn(String gatewaySn); |
| | | } |
| | |
| | | package com.dji.sample.manage.service.impl; |
| | | |
| | | import com.dji.sample.component.mqtt.model.StateDataEnum; |
| | | import com.dji.sample.component.redis.RedisConst; |
| | | import com.dji.sample.component.redis.RedisOpsUtils; |
| | | import com.dji.sample.manage.model.dto.CapacityCameraDTO; |
| | | import com.dji.sample.manage.model.dto.DeviceDictionaryDTO; |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void saveCapacityCameraReceiverList(List<CapacityCameraReceiver> capacityCameraReceivers, String deviceSn) { |
| | | public void saveCapacityCameraReceiverList(List<CapacityCameraReceiver> capacityCameraReceivers, String deviceSn, Long timestamp) { |
| | | List<CapacityCameraDTO> capacity = capacityCameraReceivers.stream() |
| | | .map(this::receiver2Dto).collect(Collectors.toList()); |
| | | redisOps.hashSet(StateDataEnum.LIVE_CAPACITY.getDesc(), deviceSn, capacity); |
| | | redisOps.setWithExpire(StateDataEnum.LIVE_CAPACITY + RedisConst.DELIMITER + deviceSn, timestamp, RedisConst.DEVICE_ALIVE_SECOND); |
| | | } |
| | | |
| | | @Override |
| New file |
| | |
| | | package com.dji.sample.manage.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.dji.sample.common.model.ResponseResult; |
| | | import com.dji.sample.component.mqtt.model.*; |
| | | import com.dji.sample.component.mqtt.service.impl.MessageSenderServiceImpl; |
| | | import com.dji.sample.component.redis.RedisConst; |
| | | import com.dji.sample.component.redis.RedisOpsUtils; |
| | | import com.dji.sample.component.websocket.model.CustomWebSocketMessage; |
| | | import com.dji.sample.component.websocket.service.IWebSocketManageService; |
| | | import com.dji.sample.component.websocket.service.impl.SendMessageServiceImpl; |
| | | import com.dji.sample.manage.dao.IDeviceFirmwareMapper; |
| | | import com.dji.sample.manage.model.dto.DeviceDTO; |
| | | import com.dji.sample.manage.model.dto.DeviceFirmwareDTO; |
| | | import com.dji.sample.manage.model.dto.DeviceFirmwareNoteDTO; |
| | | import com.dji.sample.manage.model.dto.DeviceFirmwareUpgradeDTO; |
| | | import com.dji.sample.manage.model.entity.DeviceFirmwareEntity; |
| | | import com.dji.sample.manage.model.enums.UserTypeEnum; |
| | | import com.dji.sample.manage.model.param.DeviceOtaCreateParam; |
| | | import com.dji.sample.manage.service.IDeviceFirmwareService; |
| | | import com.fasterxml.jackson.core.type.TypeReference; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.integration.annotation.ServiceActivator; |
| | | import org.springframework.integration.mqtt.support.MqttHeaders; |
| | | import org.springframework.messaging.MessageHeaders; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.time.Instant; |
| | | import java.time.LocalDate; |
| | | import java.time.ZoneId; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/8/16 |
| | | */ |
| | | @Service |
| | | @Slf4j |
| | | public class DeviceFirmwareServiceImpl implements IDeviceFirmwareService { |
| | | |
| | | @Autowired |
| | | private IDeviceFirmwareMapper mapper; |
| | | |
| | | @Autowired |
| | | private RedisOpsUtils redisOps; |
| | | |
| | | @Autowired |
| | | private MessageSenderServiceImpl messageSenderService; |
| | | |
| | | @Autowired |
| | | private ObjectMapper objectMapper; |
| | | |
| | | @Autowired |
| | | private SendMessageServiceImpl webSocketMessageService; |
| | | |
| | | @Autowired |
| | | private IWebSocketManageService webSocketManageService; |
| | | |
| | | @Override |
| | | public Optional<DeviceFirmwareDTO> getFirmware(String deviceName, String version) { |
| | | return Optional.ofNullable(entity2Dto(mapper.selectOne( |
| | | new LambdaQueryWrapper<DeviceFirmwareEntity>() |
| | | .eq(DeviceFirmwareEntity::getDeviceName, deviceName) |
| | | .eq(DeviceFirmwareEntity::getFirmwareVersion, version)))); |
| | | } |
| | | |
| | | @Override |
| | | public Optional<DeviceFirmwareNoteDTO> getLatestFirmwareReleaseNote(String deviceName) { |
| | | return Optional.ofNullable(entity2NoteDto(mapper.selectOne( |
| | | new LambdaQueryWrapper<DeviceFirmwareEntity>() |
| | | .eq(DeviceFirmwareEntity::getDeviceName, deviceName) |
| | | .eq(DeviceFirmwareEntity::getStatus, true) |
| | | .orderByDesc(DeviceFirmwareEntity::getReleaseDate) |
| | | .last(" limit 1 ")))); |
| | | } |
| | | |
| | | @Override |
| | | public List<DeviceOtaCreateParam> getDeviceOtaFirmware(List<DeviceFirmwareUpgradeDTO> upgradeDTOS) { |
| | | List<DeviceOtaCreateParam> deviceOtaList = new ArrayList<>(); |
| | | upgradeDTOS.forEach(upgradeDevice -> { |
| | | boolean exist = redisOps.getExpire(RedisConst.DEVICE_ONLINE_PREFIX + upgradeDevice.getSn()) > 0; |
| | | if (!exist) { |
| | | throw new IllegalArgumentException("Device is offline."); |
| | | } |
| | | Optional<DeviceFirmwareDTO> firmwareOpt = this.getFirmware( |
| | | upgradeDevice.getDeviceName(), upgradeDevice.getProductVersion()); |
| | | if (firmwareOpt.isEmpty()) { |
| | | throw new IllegalArgumentException("This firmware version does not exist."); |
| | | } |
| | | if (!firmwareOpt.get().getFirmwareStatus()) { |
| | | throw new IllegalArgumentException("This firmware version is not available."); |
| | | } |
| | | DeviceOtaCreateParam ota = dto2OtaCreateDto(firmwareOpt.get()); |
| | | ota.setSn(upgradeDevice.getSn()); |
| | | ota.setFirmwareUpgradeType(upgradeDevice.getFirmwareUpgradeType()); |
| | | deviceOtaList.add(ota); |
| | | }); |
| | | return deviceOtaList; |
| | | } |
| | | |
| | | @Override |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_OTA_PROGRESS, outputChannel = ChannelName.OUTBOUND) |
| | | public void handleOtaProgress(CommonTopicReceiver receiver, MessageHeaders headers) { |
| | | String topic = headers.get(MqttHeaders.RECEIVED_TOPIC).toString(); |
| | | String sn = topic.substring((TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT).length(), |
| | | topic.indexOf(TopicConst.EVENTS_SUF)); |
| | | |
| | | EventsReceiver<EventsOutputReceiver> eventsReceiver = objectMapper.convertValue(receiver.getData(), |
| | | new TypeReference<EventsReceiver<EventsOutputReceiver>>(){}); |
| | | eventsReceiver.setBid(receiver.getBid()); |
| | | eventsReceiver.setSn(sn); |
| | | |
| | | EventsOutputReceiver output = eventsReceiver.getOutput(); |
| | | log.info("SN: {}, {} ===> Upgrading progress: {}", |
| | | sn, receiver.getMethod(), output.getProgress().toString()); |
| | | |
| | | if (eventsReceiver.getResult() != ResponseResult.CODE_SUCCESS) { |
| | | log.error("SN: {}, {} ===> Error code: {}", sn, receiver.getMethod(), eventsReceiver.getResult()); |
| | | } |
| | | |
| | | DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + sn); |
| | | String childDeviceSn = device.getChildDeviceSn(); |
| | | boolean upgrade = redisOps.getExpire(RedisConst.FIRMWARE_UPGRADING_PREFIX + sn) > 0; |
| | | boolean childUpgrade = redisOps.getExpire(RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn) > 0; |
| | | |
| | | // Determine whether it is the ending state, delete the update state key in redis after the job ends. |
| | | EventsResultStatusEnum statusEnum = EventsResultStatusEnum.find(output.getStatus()); |
| | | if (upgrade) { |
| | | if (statusEnum.getEnd()) { |
| | | // Delete the cache after the update is complete. |
| | | redisOps.del(RedisConst.FIRMWARE_UPGRADING_PREFIX + sn); |
| | | } else { |
| | | // Update the update progress of the dock in redis. |
| | | redisOps.setWithExpire( |
| | | RedisConst.FIRMWARE_UPGRADING_PREFIX + sn, output.getProgress().getPercent(), |
| | | RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND); |
| | | } |
| | | } |
| | | if (childUpgrade) { |
| | | if (statusEnum.getEnd()) { |
| | | redisOps.del(RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn); |
| | | } else { |
| | | // Update the update progress of the drone in redis. |
| | | redisOps.setWithExpire( |
| | | RedisConst.FIRMWARE_UPGRADING_PREFIX + childDeviceSn, output.getProgress().getPercent(), |
| | | RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND); |
| | | } |
| | | } |
| | | |
| | | webSocketMessageService.sendBatch( |
| | | webSocketManageService.getValueWithWorkspaceAndUserType( |
| | | device.getWorkspaceId(), UserTypeEnum.WEB.getVal()), |
| | | CustomWebSocketMessage.builder() |
| | | .data(eventsReceiver) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .bizCode(receiver.getMethod()) |
| | | .build()); |
| | | |
| | | if (receiver.getNeedReply() != null && receiver.getNeedReply() == 1) { |
| | | String replyTopic = headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF; |
| | | messageSenderService.publish(replyTopic, |
| | | CommonTopicResponse.builder() |
| | | .tid(receiver.getTid()) |
| | | .bid(receiver.getBid()) |
| | | .method(receiver.getMethod()) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .data(ResponseResult.success()) |
| | | .build()); |
| | | } |
| | | } |
| | | |
| | | private DeviceFirmwareNoteDTO entity2NoteDto (DeviceFirmwareEntity entity) { |
| | | if (entity == null) { |
| | | return null; |
| | | } |
| | | return DeviceFirmwareNoteDTO.builder() |
| | | .deviceName(entity.getDeviceName()) |
| | | .productVersion(entity.getFirmwareVersion()) |
| | | .releasedTime(LocalDate.ofInstant(Instant.ofEpochMilli(entity.getReleaseDate()), ZoneId.systemDefault())) |
| | | .releaseNote(entity.getReleaseNote()) |
| | | .build(); |
| | | } |
| | | |
| | | private DeviceFirmwareDTO entity2Dto (DeviceFirmwareEntity entity) { |
| | | if (entity == null) { |
| | | return null; |
| | | } |
| | | return DeviceFirmwareDTO.builder() |
| | | .deviceName(entity.getDeviceName()) |
| | | .fileMd5(entity.getFileMd5()) |
| | | .fileSize(entity.getFileSize()) |
| | | .fileUrl(entity.getFileUrl()) |
| | | .firmwareId(entity.getFirmwareId()) |
| | | .fileName(entity.getFileName()) |
| | | .productVersion(entity.getFirmwareVersion()) |
| | | .releasedTime(LocalDate.ofInstant(Instant.ofEpochMilli(entity.getReleaseDate()), ZoneId.systemDefault())) |
| | | .firmwareStatus(entity.getStatus()) |
| | | .build(); |
| | | } |
| | | |
| | | private DeviceOtaCreateParam dto2OtaCreateDto(DeviceFirmwareDTO dto) { |
| | | if (dto == null) { |
| | | return null; |
| | | } |
| | | return DeviceOtaCreateParam.builder() |
| | | .fileSize(dto.getFileSize()) |
| | | .fileUrl(dto.getFileUrl()) |
| | | .fileName(dto.getFileName()) |
| | | .md5(dto.getFileMd5()) |
| | | .productVersion(dto.getProductVersion()) |
| | | .build(); |
| | | } |
| | | } |
| | |
| | | import java.time.LocalDateTime; |
| | | import java.time.ZoneId; |
| | | import java.util.*; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | @Autowired |
| | | private WebSocketManageServiceImpl webSocketManageService; |
| | | |
| | | private static final Pattern PATTERN_KEY = Pattern.compile( |
| | | HmsEnum.FormatKeyEnum.KEY_START + |
| | | "(" + |
| | | Arrays.stream(HmsEnum.FormatKeyEnum.values()) |
| | | .map(HmsEnum.FormatKeyEnum::getKey) |
| | | .collect(Collectors.joining("|")) + |
| | | ")"); |
| | | |
| | | @Override |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_HMS) |
| | | public void handleHms(CommonTopicReceiver receiver, MessageHeaders headers) { |
| | | String topic = headers.get(MqttHeaders.RECEIVED_TOPIC).toString(); |
| | | String sn = topic.substring((TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT).length(), |
| | | topic.indexOf(TopicConst.EVENTS_SUF)); |
| | | |
| | | DeviceHmsEntity entity = DeviceHmsEntity.builder() |
| | | .bid(receiver.getBid()) |
| | | .tid(receiver.getTid()) |
| | | .createTime(receiver.getTimestamp()) |
| | | .updateTime(0L) |
| | | .sn(sn) |
| | | .build(); |
| | | String key = RedisConst.HMS_PREFIX + sn; |
| | | // Query all unread hms messages of the device in redis. |
| | | Set<String> hmsMap = redisOps.listGetAll(key).stream().map(String::valueOf).collect(Collectors.toSet()); |
| | | |
| | | DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + sn); |
| | | |
| | | List<DeviceHmsDTO> unReadList = new ArrayList<>(); |
| | | objectMapper.convertValue(((Map) (receiver.getData())).get(MapKeyConst.LIST), |
| | | new TypeReference<List<DeviceHmsReceiver>>() {}) |
| | | .forEach(hmsReceiver -> { |
| | | final DeviceHmsEntity hms = entity.clone(); |
| | | this.fillEntity(hms, hmsReceiver); |
| | | // The same unread hms are no longer incremented. |
| | | if (hmsMap.contains(hms.getHmsKey())) { |
| | | return; |
| | | } |
| | | this.fillMessage(hms, hmsReceiver.getArgs()); |
| | | unReadList.add(entity2Dto(hms)); |
| | | mapper.insert(hms); |
| | | }); |
| | | |
| | | if (unReadList.isEmpty()) { |
| | | return; |
| | | } |
| | | redisOps.listRPush(key, unReadList.stream().map(DeviceHmsDTO::getKey).toArray(String[]::new)); |
| | | // push to the web |
| | | Collection<ConcurrentWebSocketSession> sessions = webSocketManageService.getValueWithWorkspaceAndUserType( |
| | | device.getWorkspaceId(), UserTypeEnum.WEB.getVal()); |
| | | sendMessageService.sendBatch(sessions, CustomWebSocketMessage.builder() |
| | | .bizCode(BizCodeEnum.DEVICE_HMS.getCode()) |
| | | .data(TelemetryDTO.<List<DeviceHmsDTO>>builder().sn(sn).host(unReadList).build()) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .build()); |
| | | } |
| | | |
| | | @Override |
| | |
| | | new LambdaUpdateWrapper<DeviceHmsEntity>() |
| | | .eq(DeviceHmsEntity::getSn, deviceSn) |
| | | .eq(DeviceHmsEntity::getUpdateTime, 0L)); |
| | | // Delete unread messages cached in redis. |
| | | redisOps.del(RedisConst.HMS_PREFIX + deviceSn); |
| | | } |
| | | |
| | |
| | | .build(); |
| | | } |
| | | |
| | | /** |
| | | * Populate the received data into the entity. Please refer to the documentation for splicing rules. |
| | | * @param dto |
| | | * @param receiver |
| | | */ |
| | | private void fillEntity(DeviceHmsEntity dto, DeviceHmsReceiver receiver) { |
| | | dto.setLevel(receiver.getLevel()); |
| | | dto.setModule(receiver.getModule()); |
| | | dto.setHmsId(UUID.randomUUID().toString()); |
| | | |
| | | if (HmsEnum.DomainType.DRONE_NEST.getDomain().equals(receiver.getDomainType())) { |
| | | dto.setHmsKey(HmsEnum.HmsFaqIdEnum.DOCK_TIP.getText() + receiver.getCode()); |
| | | return; |
| | | } |
| | | StringBuilder key = new StringBuilder(HmsEnum.HmsFaqIdEnum.FPV_TIP.getText()).append(receiver.getCode()); |
| | | |
| | | if (receiver.getInTheSky() == HmsEnum.IN_THE_SKY.getVal()) { |
| | | key.append(HmsEnum.IN_THE_SKY.getText()); |
| | | } |
| | | dto.setHmsKey(key.toString()); |
| | | } |
| | | |
| | | /** |
| | | * Replace wildcards in messages according to the relevant rules. |
| | | * Please refer to the documentation for splicing rules. |
| | | * @param dto |
| | | * @param args |
| | | */ |
| | | private void fillMessage(DeviceHmsEntity dto, HmsArgsReceiver args) { |
| | | HmsMessage hmsMessage = HmsJsonUtil.get(dto.getHmsKey()); |
| | | String zh = StringUtils.hasText(hmsMessage.getZh()) ? hmsMessage.getZh() : String.format("未知错误(%s)", dto.getHmsKey()); |
| | | String en = StringUtils.hasText(hmsMessage.getEn()) ? hmsMessage.getEn() : String.format("Unknown(%s)", dto.getHmsKey());// |
| | | |
| | | dto.setMessageZh(format(Locale.CHINESE.getLanguage(), zh, args)); |
| | | dto.setMessageEn(format(Locale.ENGLISH.getLanguage(), en, args)); |
| | | } |
| | | |
| | | /** |
| | | * Set the matching parameters for key. |
| | | * @param l language: zh or en |
| | | * @param hmsArgs |
| | | * @return |
| | | */ |
| | | private List<String> fillKeyArgs(String l, HmsArgsReceiver hmsArgs) { |
| | | List<String> args = new ArrayList<>(); |
| | | args.add(Objects.nonNull(hmsArgs.getAlarmId()) ? Long.toHexString(hmsArgs.getAlarmId()) : null); |
| | | args.add(Objects.nonNull(hmsArgs.getComponentIndex()) ? String.valueOf(hmsArgs.getComponentIndex() + 1) : null); |
| | | if (Objects.nonNull(hmsArgs.getSensorIndex())) { |
| | | args.add(String.valueOf(hmsArgs.getSensorIndex() + 1)); |
| | | |
| | | HmsEnum.HmsBatteryIndexEnum hmsBatteryIndexEnum = HmsEnum.HmsBatteryIndexEnum.find(hmsArgs.getSensorIndex()); |
| | | HmsEnum.HmsDockCoverIndexEnum hmsDockCoverIndexEnum = HmsEnum.HmsDockCoverIndexEnum.find(hmsArgs.getSensorIndex()); |
| | | HmsEnum.HmsChargingRodIndexEnum hmsChargingRodIndexEnum = HmsEnum.HmsChargingRodIndexEnum.find(hmsArgs.getSensorIndex()); |
| | | |
| | | switch (l) { |
| | | case "zh": |
| | | args.add(hmsBatteryIndexEnum.getZh()); |
| | | args.add(hmsDockCoverIndexEnum.getZh()); |
| | | args.add(hmsChargingRodIndexEnum.getZh()); |
| | | break; |
| | | case "en": |
| | | args.add(hmsBatteryIndexEnum.getEn()); |
| | | args.add(hmsDockCoverIndexEnum.getEn()); |
| | | args.add(hmsChargingRodIndexEnum.getEn()); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | } |
| | | return args; |
| | | } |
| | | |
| | | /** |
| | | * Returns a formatted string using the specified locale, format string, and arguments. |
| | | * @param l language: zh or en |
| | | * @param format |
| | | * @param hmsArgs |
| | | * @return |
| | | */ |
| | | private String format(String l, String format, HmsArgsReceiver hmsArgs) { |
| | | List<String> args = fillKeyArgs(l, hmsArgs); |
| | | List<String> list = parse(format); |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (String word : list) { |
| | | if (!StringUtils.hasText(word)) { |
| | | continue; |
| | | } |
| | | HmsEnum.FormatKeyEnum keyEnum = HmsEnum.FormatKeyEnum.find(word.substring(1)); |
| | | sb.append(HmsEnum.FormatKeyEnum.KEY_START != word.charAt(0) || HmsEnum.FormatKeyEnum.UNKNOWN == keyEnum ? |
| | | word : args.get(keyEnum.getIndex())); |
| | | } |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** |
| | | * Finds format specifiers in the format string. |
| | | * @param s |
| | | * @return |
| | | */ |
| | | private List<String> parse(String s) { |
| | | List<String> list = new ArrayList<>(); |
| | | Matcher matcher = PATTERN_KEY.matcher(s); |
| | | for (int i = 0; i < s.length(); ) { |
| | | if (matcher.find(i)) { |
| | | if (matcher.start() != i) { |
| | | list.add(s.substring(i, matcher.start())); |
| | | } |
| | | list.add(matcher.group()); |
| | | i = matcher.end(); |
| | | } else { |
| | | list.add(s.substring(i)); |
| | | break; |
| | | } |
| | | } |
| | | return list; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.dji.sample.common.model.Pagination; |
| | | import com.dji.sample.common.model.PaginationData; |
| | | import com.dji.sample.common.model.ResponseResult; |
| | | import com.dji.sample.component.mqtt.model.*; |
| | | import com.dji.sample.component.mqtt.service.IMessageSenderService; |
| | | import com.dji.sample.component.redis.RedisConst; |
| | | import com.dji.sample.component.redis.RedisOpsUtils; |
| | | import com.dji.sample.component.websocket.model.CustomWebSocketMessage; |
| | | import com.dji.sample.component.websocket.service.ISendMessageService; |
| | | import com.dji.sample.component.websocket.service.IWebSocketManageService; |
| | | import com.dji.sample.manage.dao.IDeviceLogsMapper; |
| | | import com.dji.sample.manage.model.dto.*; |
| | | import com.dji.sample.manage.model.entity.DeviceLogsEntity; |
| | | import com.dji.sample.manage.model.enums.DeviceDomainEnum; |
| | | import com.dji.sample.manage.model.enums.DeviceLogsStatusEnum; |
| | | import com.dji.sample.manage.model.enums.LogsFileUpdateMethodEnum; |
| | | import com.dji.sample.manage.model.enums.UserTypeEnum; |
| | | import com.dji.sample.manage.model.param.DeviceLogsCreateParam; |
| | | import com.dji.sample.manage.model.param.DeviceLogsQueryParam; |
| | | import com.dji.sample.manage.model.param.LogsFileUpdateParam; |
| | | import com.dji.sample.manage.model.receiver.*; |
| | | import com.dji.sample.manage.service.IDeviceLogsService; |
| | | import com.dji.sample.manage.service.ILogsFileService; |
| | | import com.dji.sample.manage.service.ITopologyService; |
| | | import com.dji.sample.media.model.StsCredentialsDTO; |
| | | import com.dji.sample.storage.service.IStorageService; |
| | | import com.fasterxml.jackson.core.type.TypeReference; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.integration.annotation.ServiceActivator; |
| | | import org.springframework.integration.mqtt.support.MqttHeaders; |
| | | import org.springframework.messaging.MessageHeaders; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.net.URL; |
| | | import java.time.Instant; |
| | | import java.time.LocalDateTime; |
| | | import java.time.ZoneId; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | @Service |
| | | @Transactional |
| | | @Slf4j |
| | | public class DeviceLogsServiceImpl implements IDeviceLogsService { |
| | | |
| | | private static final String LOGS_FILE_SUFFIX = ".tar"; |
| | | |
| | | @Autowired |
| | | private IDeviceLogsMapper mapper; |
| | | |
| | | @Autowired |
| | | private ITopologyService topologyService; |
| | | |
| | | @Autowired |
| | | private IMessageSenderService messageSenderService; |
| | | |
| | | @Autowired |
| | | private ILogsFileService logsFileService; |
| | | |
| | | @Autowired |
| | | private RedisOpsUtils redisOpsUtils; |
| | | |
| | | @Autowired |
| | | private IStorageService storageService; |
| | | |
| | | @Autowired |
| | | private ObjectMapper objectMapper; |
| | | |
| | | @Autowired |
| | | private ISendMessageService webSocketMessageService; |
| | | |
| | | @Autowired |
| | | private IWebSocketManageService webSocketManageService; |
| | | |
| | | @Override |
| | | public PaginationData<DeviceLogsDTO> getUploadedLogs(String deviceSn, DeviceLogsQueryParam param) { |
| | | LambdaQueryWrapper<DeviceLogsEntity> queryWrapper = new LambdaQueryWrapper<DeviceLogsEntity>() |
| | | .eq(DeviceLogsEntity::getDeviceSn, deviceSn) |
| | | .between(Objects.nonNull(param.getBeginTime()) && Objects.nonNull(param.getEndTime()), |
| | | DeviceLogsEntity::getCreateTime, param.getBeginTime(), param.getEndTime()) |
| | | .eq(Objects.nonNull(param.getStatus()), DeviceLogsEntity::getStatus, param.getStatus()) |
| | | .like(StringUtils.hasText(param.getLogsInformation()), |
| | | DeviceLogsEntity::getLogsInfo, param.getLogsInformation()) |
| | | .orderByDesc(DeviceLogsEntity::getCreateTime); |
| | | |
| | | Page<DeviceLogsEntity> pagination = mapper.selectPage(new Page<>(param.getPage(), param.getPageSize()), queryWrapper); |
| | | |
| | | List<DeviceLogsDTO> deviceLogsList = pagination.getRecords().stream().map(this::entity2Dto).collect(Collectors.toList()); |
| | | |
| | | return new PaginationData<DeviceLogsDTO>(deviceLogsList, new Pagination(pagination)); |
| | | } |
| | | |
| | | @Override |
| | | public ResponseResult getRealTimeLogs(String deviceSn, List<String> domainList) { |
| | | boolean exist = redisOpsUtils.getExpire(RedisConst.DEVICE_ONLINE_PREFIX + deviceSn) > 0; |
| | | if (!exist) { |
| | | return ResponseResult.error("Device is offline."); |
| | | } |
| | | |
| | | String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + deviceSn + TopicConst.SERVICES_SUF; |
| | | Optional<LogsFileUploadList> serviceReplyOpt = messageSenderService.publishWithReply( |
| | | LogsFileUploadList.class, |
| | | topic, |
| | | CommonTopicResponse.builder() |
| | | .tid(UUID.randomUUID().toString()) |
| | | .bid(UUID.randomUUID().toString()) |
| | | .method(ServicesMethodEnum.FILE_UPLOAD_LIST.getMethod()) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .data(Map.of(MapKeyConst.MODULE_LIST, domainList)) |
| | | .build(), 1); |
| | | if (serviceReplyOpt.isEmpty()) { |
| | | return ResponseResult.error("No message reply received."); |
| | | } |
| | | LogsFileUploadList data = serviceReplyOpt.get(); |
| | | for (LogsFileUpload file : data.getFiles()) { |
| | | if (file.getDeviceSn().isBlank()) { |
| | | file.setDeviceSn(deviceSn); |
| | | } |
| | | } |
| | | return ResponseResult.success(data); |
| | | } |
| | | |
| | | @Override |
| | | public String insertDeviceLogs(String bid, String username, String deviceSn, DeviceLogsCreateParam param) { |
| | | DeviceLogsEntity entity = DeviceLogsEntity.builder() |
| | | .deviceSn(deviceSn) |
| | | .username(username) |
| | | .happenTime(param.getHappenTime()) |
| | | .logsInfo(Objects.requireNonNullElse(param.getLogsInformation(), "")) |
| | | .logsId(bid) |
| | | .status(DeviceLogsStatusEnum.UPLOADING.getVal()) |
| | | .build(); |
| | | boolean insert = mapper.insert(entity) > 0; |
| | | if (!insert) { |
| | | return ""; |
| | | } |
| | | for (LogsFileUpload file : param.getFiles()) { |
| | | insert = logsFileService.insertFile(file, entity.getLogsId()); |
| | | if (!insert) { |
| | | return ""; |
| | | } |
| | | } |
| | | |
| | | return bid; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public ResponseResult pushFileUpload(String username, String deviceSn, DeviceLogsCreateParam param) { |
| | | StsCredentialsDTO stsCredentials = storageService.getSTSCredentials(); |
| | | LogsUploadCredentialsDTO credentialsDTO = new LogsUploadCredentialsDTO(stsCredentials); |
| | | // Set the storage name of the file. |
| | | List<LogsFileUpload> files = param.getFiles(); |
| | | files.forEach(file -> file.setObjectKey(credentialsDTO.getObjectKeyPrefix() + "/" + UUID.randomUUID().toString() + LOGS_FILE_SUFFIX)); |
| | | |
| | | credentialsDTO.setParams(LogsFileUploadList.builder().files(files).build()); |
| | | String bid = UUID.randomUUID().toString(); |
| | | Optional<ServiceReply> serviceReply = messageSenderService.publishWithReply( |
| | | TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + deviceSn + TopicConst.SERVICES_SUF, |
| | | CommonTopicResponse.<LogsUploadCredentialsDTO>builder() |
| | | .tid(UUID.randomUUID().toString()) |
| | | .bid(bid) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .method(ServicesMethodEnum.FILE_UPLOAD_START.getMethod()) |
| | | .data(credentialsDTO) |
| | | .build()); |
| | | |
| | | if (serviceReply.isEmpty()) { |
| | | return ResponseResult.error("No message reply received."); |
| | | } |
| | | ServiceReply reply = serviceReply.get(); |
| | | if (ResponseResult.CODE_SUCCESS != reply.getResult()) { |
| | | return ResponseResult.error(String.valueOf(reply.getResult())); |
| | | } |
| | | |
| | | String logsId = this.insertDeviceLogs(bid, username, deviceSn, param); |
| | | if (!bid.equals(logsId)) { |
| | | return ResponseResult.error("Database insert failed."); |
| | | } |
| | | |
| | | // Save the status of the log upload. |
| | | redisOpsUtils.hashSet(RedisConst.LOGS_FILE_PREFIX + deviceSn, bid, LogsOutputProgressDTO.builder().logsId(logsId).build()); |
| | | return ResponseResult.success(); |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public ResponseResult pushUpdateFile(String deviceSn, LogsFileUpdateParam param) { |
| | | LogsFileUpdateMethodEnum method = LogsFileUpdateMethodEnum.find(param.getStatus()); |
| | | if (LogsFileUpdateMethodEnum.UNKNOWN == method) { |
| | | return ResponseResult.error("Illegal param"); |
| | | } |
| | | String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + deviceSn + TopicConst.SERVICES_SUF; |
| | | String bid = UUID.randomUUID().toString(); |
| | | Optional<ServiceReply> serviceReply = messageSenderService.publishWithReply(topic, |
| | | CommonTopicResponse.<LogsFileUpdateParam>builder() |
| | | .tid(UUID.randomUUID().toString()) |
| | | .bid(bid) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .method(ServicesMethodEnum.FILE_UPLOAD_UPDATE.getMethod()) |
| | | .data(param) |
| | | .build()); |
| | | |
| | | if (serviceReply.isEmpty()) { |
| | | return ResponseResult.error("No message reply received."); |
| | | } |
| | | ServiceReply reply = serviceReply.get(); |
| | | if (ResponseResult.CODE_SUCCESS != reply.getResult()) { |
| | | return ResponseResult.error("Error Code : " + reply.getResult()); |
| | | } |
| | | |
| | | return ResponseResult.success(); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteLogs(String deviceSn, String logsId) { |
| | | mapper.delete(new LambdaUpdateWrapper<DeviceLogsEntity>() |
| | | .eq(DeviceLogsEntity::getLogsId, logsId).eq(DeviceLogsEntity::getDeviceSn, deviceSn)); |
| | | logsFileService.deleteFileByLogsId(logsId); |
| | | } |
| | | |
| | | @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_FILE_UPLOAD_PROGRESS, outputChannel = ChannelName.OUTBOUND) |
| | | @Override |
| | | public void handleFileUploadProgress(CommonTopicReceiver receiver, MessageHeaders headers) { |
| | | String topic = headers.get(MqttHeaders.RECEIVED_TOPIC).toString(); |
| | | String sn = topic.substring((TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT).length(), |
| | | topic.indexOf(TopicConst.EVENTS_SUF)); |
| | | |
| | | if (receiver.getNeedReply() != null && receiver.getNeedReply() == 1) { |
| | | String replyTopic = headers.get(MqttHeaders.RECEIVED_TOPIC) + TopicConst._REPLY_SUF; |
| | | messageSenderService.publish(replyTopic, |
| | | CommonTopicResponse.builder() |
| | | .tid(receiver.getTid()) |
| | | .bid(receiver.getBid()) |
| | | .method(receiver.getMethod()) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .data(ResponseResult.success()) |
| | | .build()); |
| | | } |
| | | |
| | | EventsReceiver<OutputLogsProgressReceiver> eventsReceiver = objectMapper.convertValue(receiver.getData(), |
| | | new TypeReference<EventsReceiver<OutputLogsProgressReceiver>>(){}); |
| | | |
| | | EventsReceiver<LogsOutputProgressDTO> webSocketData = new EventsReceiver<>(); |
| | | webSocketData.setBid(receiver.getBid()); |
| | | webSocketData.setSn(sn); |
| | | |
| | | DeviceDTO device = (DeviceDTO) redisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + sn); |
| | | |
| | | try { |
| | | OutputLogsProgressReceiver output = eventsReceiver.getOutput(); |
| | | EventsResultStatusEnum statusEnum = EventsResultStatusEnum.find(output.getStatus()); |
| | | log.info("Logs upload progress: {}", output.toString()); |
| | | |
| | | String key = RedisConst.LOGS_FILE_PREFIX + sn; |
| | | LogsOutputProgressDTO progress; |
| | | boolean exist = redisOpsUtils.checkExist(key); |
| | | if (!exist && !statusEnum.getEnd()) { |
| | | progress = LogsOutputProgressDTO.builder().logsId(receiver.getBid()).build(); |
| | | redisOpsUtils.hashSet(key, receiver.getBid(), progress); |
| | | } else if (exist) { |
| | | progress = (LogsOutputProgressDTO) redisOpsUtils.hashGet(key, receiver.getBid()); |
| | | } else { |
| | | progress = LogsOutputProgressDTO.builder().build(); |
| | | } |
| | | progress.setStatus(output.getStatus()); |
| | | |
| | | // If the logs file is empty, delete the cache of this task. |
| | | List<LogsExtFileReceiver> fileReceivers = output.getExt().getFiles(); |
| | | if (CollectionUtils.isEmpty(fileReceivers)) { |
| | | redisOpsUtils.del(RedisConst.LOGS_FILE_PREFIX + sn); |
| | | return; |
| | | } |
| | | |
| | | // refresh cache. |
| | | List<LogsProgressDTO> fileProgressList = new ArrayList<>(); |
| | | fileReceivers.forEach(file -> { |
| | | LogsProgressReceiver logsProgress = file.getProgress(); |
| | | if (!StringUtils.hasText(file.getDeviceSn())) { |
| | | if (String.valueOf(DeviceDomainEnum.DOCK.getVal()).equals(file.getDeviceModelDomain())) { |
| | | file.setDeviceSn(sn); |
| | | } else if (String.valueOf(DeviceDomainEnum.SUB_DEVICE.getVal()).equals(file.getDeviceModelDomain())) { |
| | | file.setDeviceSn(device.getChildDeviceSn()); |
| | | } |
| | | } |
| | | |
| | | fileProgressList.add(LogsProgressDTO.builder() |
| | | .deviceSn(file.getDeviceSn()) |
| | | .deviceModelDomain(file.getDeviceModelDomain()) |
| | | .result(logsProgress.getResult()) |
| | | .status(logsProgress.getStatus()) |
| | | .uploadRate(logsProgress.getUploadRate()) |
| | | .progress(((logsProgress.getCurrentStep() - 1) * 100 + logsProgress.getProgress()) / logsProgress.getTotalStep()) |
| | | .build()); |
| | | }); |
| | | progress.setFiles(fileProgressList); |
| | | webSocketData.setOutput(progress); |
| | | redisOpsUtils.hashSet(RedisConst.LOGS_FILE_PREFIX + sn, receiver.getBid(), progress); |
| | | // Delete the cache at the end of the task. |
| | | if (statusEnum.getEnd()) { |
| | | redisOpsUtils.del(RedisConst.LOGS_FILE_PREFIX + sn); |
| | | this.updateLogsStatus(receiver.getBid(), DeviceLogsStatusEnum.find(statusEnum).getVal()); |
| | | |
| | | fileReceivers.forEach(file -> logsFileService.updateFile(receiver.getBid(), file)); |
| | | } |
| | | } catch (NullPointerException e) { |
| | | this.updateLogsStatus(receiver.getBid(), DeviceLogsStatusEnum.FAILED.getVal()); |
| | | |
| | | redisOpsUtils.del(RedisConst.LOGS_FILE_PREFIX + sn); |
| | | } |
| | | |
| | | webSocketMessageService.sendBatch( |
| | | webSocketManageService.getValueWithWorkspaceAndUserType( |
| | | device.getWorkspaceId(), UserTypeEnum.WEB.getVal()), |
| | | CustomWebSocketMessage.builder() |
| | | .data(webSocketData) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .bizCode(receiver.getMethod()) |
| | | .build()); |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void updateLogsStatus(String logsId, Integer value) { |
| | | |
| | | mapper.update(DeviceLogsEntity.builder().status(value).build(), |
| | | new LambdaUpdateWrapper<DeviceLogsEntity>().eq(DeviceLogsEntity::getLogsId, logsId)); |
| | | if (DeviceLogsStatusEnum.DONE.getVal() == value) { |
| | | logsFileService.updateFileUploadStatus(logsId, true); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public URL getLogsFileUrl(String logsId, String fileId) { |
| | | return logsFileService.getLogsFileUrl(logsId, fileId); |
| | | } |
| | | |
| | | private DeviceLogsDTO entity2Dto(DeviceLogsEntity entity) { |
| | | if (Objects.isNull(entity)) { |
| | | return null; |
| | | } |
| | | String key = RedisConst.LOGS_FILE_PREFIX + entity.getDeviceSn(); |
| | | LogsOutputProgressDTO progress = new LogsOutputProgressDTO(); |
| | | if (redisOpsUtils.hashCheck(key, entity.getLogsId())) { |
| | | progress = (LogsOutputProgressDTO) redisOpsUtils.hashGet(key, entity.getLogsId()); |
| | | } |
| | | |
| | | return DeviceLogsDTO.builder() |
| | | .logsId(entity.getLogsId()) |
| | | .createTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault())) |
| | | .happenTime(Objects.isNull(entity.getHappenTime()) ? |
| | | null : LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getHappenTime()), ZoneId.systemDefault())) |
| | | .status(entity.getStatus()) |
| | | .logsInformation(entity.getLogsInfo()) |
| | | .userName(entity.getUsername()) |
| | | .deviceLogs(LogsFileUploadList.builder().files(logsFileService.getLogsFileByLogsId(entity.getLogsId())).build()) |
| | | .logsProgress(progress.getFiles()) |
| | | .deviceTopo(topologyService.getDeviceTopologyByGatewaySn(entity.getDeviceSn()).orElse(null)) |
| | | .build(); |
| | | } |
| | | } |
| | |
| | | import com.dji.sample.manage.service.ICapacityCameraService; |
| | | import com.dji.sample.manage.service.IDeviceDictionaryService; |
| | | import com.dji.sample.manage.service.IDevicePayloadService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | * @version 0.1 |
| | | * @date 2021/11/19 |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | @Transactional |
| | | public class DevicePayloadServiceImpl implements IDevicePayloadService { |
| | |
| | | .eq(DevicePayloadEntity::getDeviceSn, receiver.getSn())); |
| | | } |
| | | |
| | | @Override |
| | | public void saveDeviceBasicPayload(List<DevicePayloadReceiver> payloadReceiverList, Long timestamp) { |
| | | if (payloadReceiverList.isEmpty()) { |
| | | return; |
| | | } |
| | | String deviceSn = payloadReceiverList.stream().findAny().get().getDeviceSn(); |
| | | String key = RedisConst.STATE_PAYLOAD_PREFIX + deviceSn; |
| | | // Solve timing problems |
| | | long last = (long) Objects.requireNonNullElse(redisOps.get(key), 0L); |
| | | if (last > timestamp) { |
| | | return; |
| | | } |
| | | |
| | | |
| | | // Filter unsaved payload information. |
| | | Set<String> payloadSns = this.getDevicePayloadEntitiesByDeviceSn(payloadReceiverList.get(0).getDeviceSn()) |
| | | .stream().map(DevicePayloadDTO::getPayloadSn).collect(Collectors.toSet()); |
| | | |
| | | Set<String> newPayloadSns = payloadReceiverList.stream().map(DevicePayloadReceiver::getSn).collect(Collectors.toSet()); |
| | | Set<String> needToDel = payloadSns.stream().filter(sn -> !newPayloadSns.contains(sn)).collect(Collectors.toSet()); |
| | | this.deletePayloadsByPayloadsSn(needToDel); |
| | | |
| | | List<DevicePayloadReceiver> needToSave = payloadReceiverList.stream() |
| | | .filter(payload -> !payloadSns.contains(payload.getSn())).collect(Collectors.toList()); |
| | | |
| | | // Save the new payload information. |
| | | boolean isSave = this.savePayloadDTOs(needToSave); |
| | | if (isSave) { |
| | | redisOps.setWithExpire(key, timestamp, RedisConst.DEVICE_ALIVE_SECOND); |
| | | } |
| | | log.debug("The result of saving the payloads is {}.", isSave); |
| | | } |
| | | |
| | | @Override |
| | | public void deletePayloadsByPayloadsSn(Collection<String> payloadSns) { |
| | | if (CollectionUtils.isEmpty(payloadSns)) { |
| | | return; |
| | | } |
| | | mapper.delete(new LambdaUpdateWrapper<DevicePayloadEntity>() |
| | | .or(wrapper -> payloadSns.forEach(sn -> wrapper.eq(DevicePayloadEntity::getPayloadSn, sn)))); |
| | | } |
| | | |
| | | /** |
| | | * Convert database entity objects into payload data transfer object. |
| | | * @param entity |
| | |
| | | import com.dji.sample.common.error.CommonErrorEnum; |
| | | import com.dji.sample.common.model.Pagination; |
| | | import com.dji.sample.common.model.PaginationData; |
| | | import com.dji.sample.common.model.ResponseResult; |
| | | import com.dji.sample.component.mqtt.model.*; |
| | | import com.dji.sample.component.mqtt.service.IMessageSenderService; |
| | | import com.dji.sample.component.mqtt.service.IMqttTopicService; |
| | |
| | | import com.dji.sample.manage.model.dto.*; |
| | | import com.dji.sample.manage.model.entity.DeviceEntity; |
| | | import com.dji.sample.manage.model.enums.DeviceDomainEnum; |
| | | import com.dji.sample.manage.model.enums.DeviceFirmwareStatusEnum; |
| | | import com.dji.sample.manage.model.enums.IconUrlEnum; |
| | | import com.dji.sample.manage.model.enums.UserTypeEnum; |
| | | import com.dji.sample.manage.model.param.DeviceOtaCreateParam; |
| | | import com.dji.sample.manage.model.param.DeviceQueryParam; |
| | | import com.dji.sample.manage.model.receiver.*; |
| | | import com.dji.sample.manage.service.*; |
| | |
| | | private IWebSocketManageService webSocketManageService; |
| | | |
| | | @Autowired |
| | | private IDeviceFirmwareService deviceFirmwareService; |
| | | |
| | | @Autowired |
| | | @Qualifier("gatewayOSDServiceImpl") |
| | | private ITSAService tsaService; |
| | | |
| | |
| | | gatewayOpt.map(DeviceDTO::getWorkspaceId).ifPresent(gateway::setWorkspaceId); |
| | | redisOps.setWithExpire(key, gateway, RedisConst.DEVICE_ALIVE_SECOND); |
| | | this.pushDeviceOnlineTopo(gateway.getWorkspaceId(), gatewaySn, gatewaySn); |
| | | return true; |
| | | } |
| | | |
| | | long expire = redisOps.getExpire(key); |
| | | // If the key about the device in redis has expired, the remote control is considered to be offline. |
| | | if (expire <= 0) { |
| | | log.debug("The remote control is already offline."); |
| | | return true; |
| | | } |
| | | |
| | |
| | | String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn; |
| | | // change log: Use redis instead of |
| | | long time = redisOps.getExpire(key); |
| | | long gatewayTime = redisOps.getExpire(RedisConst.DEVICE_ONLINE_PREFIX + deviceGateway.getSn()); |
| | | long now = System.currentTimeMillis(); |
| | | |
| | | if (time > 0) { |
| | | redisOps.expireKey(RedisConst.DEVICE_ONLINE_PREFIX + deviceGateway.getSn(), RedisConst.DEVICE_ALIVE_SECOND); |
| | | if (time > 0 && gatewayTime > 0) { |
| | | redisOps.expireKey(key, RedisConst.DEVICE_ALIVE_SECOND); |
| | | DeviceDTO device = DeviceDTO.builder().loginTime(LocalDateTime.now()).deviceSn(deviceSn).build(); |
| | | DeviceDTO gateway = DeviceDTO.builder() |
| | |
| | | |
| | | @Override |
| | | public Optional<TopologyDeviceDTO> getDeviceTopoForPilot(String sn) { |
| | | if (sn.isBlank()) { |
| | | return Optional.empty(); |
| | | } |
| | | List<TopologyDeviceDTO> topologyDeviceList = this.getDevicesByParams( |
| | | DeviceQueryParam.builder() |
| | | .deviceSn(sn) |
| | |
| | | |
| | | DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + from); |
| | | |
| | | if (device == null || !StringUtils.hasText(device.getWorkspaceId())) { |
| | | return; |
| | | if (device == null) { |
| | | Optional<DeviceDTO> deviceOpt = this.getDeviceBySn(from); |
| | | if (deviceOpt.isEmpty()) { |
| | | return; |
| | | } |
| | | device = deviceOpt.get(); |
| | | if (!StringUtils.hasText(device.getWorkspaceId())) { |
| | | return; |
| | | } |
| | | redisOps.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + from, device, |
| | | RedisConst.DEVICE_ALIVE_SECOND); |
| | | this.subscribeTopicOnline(from); |
| | | } |
| | | |
| | | receiver = objectMapper.readValue(payload, CommonTopicReceiver.class); |
| | |
| | | if (entity == null) { |
| | | return null; |
| | | } |
| | | return DeviceDTO.builder() |
| | | DeviceDTO.DeviceDTOBuilder deviceDTOBuilder = DeviceDTO.builder() |
| | | .deviceSn(entity.getDeviceSn()) |
| | | .childDeviceSn(entity.getChildSn()) |
| | | .deviceName(entity.getDeviceName()) |
| | |
| | | .firmwareVersion(entity.getFirmwareVersion()) |
| | | .workspaceName(entity.getWorkspaceId() != null ? |
| | | workspaceService.getWorkspaceByWorkspaceId(entity.getWorkspaceId()) |
| | | .map(WorkspaceDTO::getWorkspaceName).orElse("") : "") |
| | | .build(); |
| | | .map(WorkspaceDTO::getWorkspaceName).orElse("") : ""); |
| | | |
| | | if (!StringUtils.hasText(entity.getFirmwareVersion())) { |
| | | return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal()).build(); |
| | | } |
| | | // Query whether the device is updating firmware. |
| | | Object progress = redisOps.get(RedisConst.FIRMWARE_UPGRADING_PREFIX + entity.getDeviceSn()); |
| | | if (Objects.nonNull(progress)) { |
| | | return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.UPGRADING.getVal()).firmwareProgress((int)progress).build(); |
| | | } |
| | | |
| | | // First query the latest firmware version of the device model and compare it with the current firmware version |
| | | // to see if it needs to be upgraded. |
| | | Optional<DeviceFirmwareNoteDTO> firmwareReleaseNoteOpt = deviceFirmwareService.getLatestFirmwareReleaseNote(entity.getDeviceName()); |
| | | if (firmwareReleaseNoteOpt.isPresent()) { |
| | | DeviceFirmwareNoteDTO firmwareNoteDTO = firmwareReleaseNoteOpt.get(); |
| | | if (firmwareNoteDTO.getProductVersion().equals(entity.getFirmwareVersion())) { |
| | | return deviceDTOBuilder.firmwareStatus(entity.getCompatibleStatus() ? |
| | | DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal() : |
| | | DeviceFirmwareStatusEnum.CONSISTENT_UPGRADE.getVal()).build(); |
| | | } |
| | | |
| | | return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.NORMAL_UPGRADE.getVal()).build(); |
| | | } |
| | | return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal()).build(); |
| | | } |
| | | |
| | | @Override |
| | |
| | | @Override |
| | | public void updateFirmwareVersion(FirmwareVersionReceiver receiver) { |
| | | if (receiver.getDomain() == DeviceDomainEnum.SUB_DEVICE) { |
| | | this.updateDevice(DeviceDTO.builder() |
| | | final DeviceDTO device = DeviceDTO.builder() |
| | | .deviceSn(receiver.getSn()) |
| | | .firmwareVersion(receiver.getFirmwareVersion()) |
| | | .build()); |
| | | .firmwareStatus(receiver.getCompatibleStatus() == null ? |
| | | null : DeviceFirmwareStatusEnum.CompatibleStatusEnum.INCONSISTENT.getVal() != receiver.getCompatibleStatus() ? |
| | | DeviceFirmwareStatusEnum.UNKNOWN.getVal() : DeviceFirmwareStatusEnum.CONSISTENT_UPGRADE.getVal()) |
| | | .build(); |
| | | this.updateDevice(device); |
| | | return; |
| | | } |
| | | payloadService.updateFirmwareVersion(receiver); |
| | | } |
| | | |
| | | @Override |
| | | public ResponseResult createDeviceOtaJob(String workspaceId, List<DeviceFirmwareUpgradeDTO> upgradeDTOS) { |
| | | List<DeviceOtaCreateParam> deviceOtaFirmwares = deviceFirmwareService.getDeviceOtaFirmware(upgradeDTOS); |
| | | if (deviceOtaFirmwares.isEmpty()) { |
| | | return ResponseResult.error(); |
| | | } |
| | | |
| | | DeviceOtaCreateParam deviceOtaFirmware = deviceOtaFirmwares.get(0); |
| | | List<DeviceDTO> devices = getDevicesByParams(DeviceQueryParam.builder().childSn(deviceOtaFirmware.getSn()).build()); |
| | | String gatewaySn = devices.isEmpty() ? deviceOtaFirmware.getSn() : devices.get(0).getDeviceSn(); |
| | | |
| | | String topic = THING_MODEL_PRE + PRODUCT + gatewaySn + SERVICES_SUF; |
| | | |
| | | // The bids in the progress messages reported subsequently are the same. |
| | | String bid = UUID.randomUUID().toString(); |
| | | Optional<ServiceReply> serviceReplyOpt = messageSender.publishWithReply( |
| | | topic, CommonTopicResponse.<Map<String, List<DeviceOtaCreateParam>>>builder() |
| | | .tid(UUID.randomUUID().toString()) |
| | | .bid(bid) |
| | | .timestamp(System.currentTimeMillis()) |
| | | .method(ServicesMethodEnum.OTA_CREATE.getMethod()) |
| | | .data(Map.of(MapKeyConst.DEVICES, deviceOtaFirmwares)) |
| | | .build()); |
| | | if (serviceReplyOpt.isEmpty()) { |
| | | return ResponseResult.error("No message reply received."); |
| | | } |
| | | ServiceReply serviceReply = serviceReplyOpt.get(); |
| | | if (serviceReply.getResult() != ResponseResult.CODE_SUCCESS) { |
| | | return ResponseResult.error(serviceReply.getResult(), "Firmware Error Code: " + serviceReply.getResult()); |
| | | } |
| | | if (ServicesMethodEnum.OTA_CREATE.getProgress()) { |
| | | // Record the device state that needs to be updated. |
| | | deviceOtaFirmwares.forEach(deviceOta -> redisOps.setWithExpire( |
| | | RedisConst.FIRMWARE_UPGRADING_PREFIX + deviceOta.getSn(), |
| | | bid, |
| | | RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND)); |
| | | } |
| | | return ResponseResult.success(); |
| | | } |
| | | |
| | | /** |
| | |
| | | .childSn(dto.getChildDeviceSn()) |
| | | .domain(StringUtils.hasText(dto.getDomain()) ? DeviceDomainEnum.getVal(dto.getDomain()) : null) |
| | | .firmwareVersion(dto.getFirmwareVersion()) |
| | | .compatibleStatus(dto.getFirmwareStatus() == null ? null : |
| | | DeviceFirmwareStatusEnum.CONSISTENT_UPGRADE != DeviceFirmwareStatusEnum.find(dto.getFirmwareStatus())) |
| | | .build(); |
| | | } |
| | | |
| | |
| | | import com.dji.sample.component.mqtt.model.CommonTopicResponse; |
| | | import com.dji.sample.component.mqtt.model.ServiceReply; |
| | | import com.dji.sample.component.mqtt.model.ServicesMethodEnum; |
| | | import com.dji.sample.component.mqtt.model.StateDataEnum; |
| | | import com.dji.sample.component.mqtt.service.IMessageSenderService; |
| | | import com.dji.sample.component.redis.RedisConst; |
| | | import com.dji.sample.component.redis.RedisOpsUtils; |
| | |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Optional; |
| | | import java.util.UUID; |
| | | import java.util.*; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.stream.Collectors; |
| | | |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void saveLiveCapacity(LiveCapacityReceiver liveCapacityReceiver) { |
| | | public void saveLiveCapacity(LiveCapacityReceiver liveCapacityReceiver, Long timestamp) { |
| | | // Solve timing problems |
| | | for (CapacityDeviceReceiver capacityDeviceReceiver : liveCapacityReceiver.getDeviceList()) { |
| | | long last = (long) Objects.requireNonNullElse( |
| | | redisOps.get(StateDataEnum.LIVE_CAPACITY + RedisConst.DELIMITER + capacityDeviceReceiver.getSn()), 0L); |
| | | if (last > timestamp) { |
| | | return; |
| | | } |
| | | capacityCameraService.saveCapacityCameraReceiverList( |
| | | capacityDeviceReceiver.getCameraList(), |
| | | capacityDeviceReceiver.getSn()); |
| | | capacityDeviceReceiver.getSn(), timestamp); |
| | | } |
| | | } |
| | | |
| New file |
| | |
| | | package com.dji.sample.manage.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.dji.sample.manage.dao.ILogsFileIndexMapper; |
| | | import com.dji.sample.manage.model.dto.LogsFileDTO; |
| | | import com.dji.sample.manage.model.entity.LogsFileIndexEntity; |
| | | import com.dji.sample.manage.model.receiver.LogsFile; |
| | | import com.dji.sample.manage.model.receiver.LogsFileUpload; |
| | | import com.dji.sample.manage.service.ILogsFileIndexService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | import java.util.Optional; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/8 |
| | | */ |
| | | @Service |
| | | @Transactional |
| | | public class LogsFileIndexServiceImpl implements ILogsFileIndexService { |
| | | |
| | | @Autowired |
| | | private ILogsFileIndexMapper mapper; |
| | | |
| | | @Override |
| | | public Boolean insertFileIndex(LogsFile file, String deviceSn, Integer domain, String fileId) { |
| | | if (Objects.isNull(file)) { |
| | | return false; |
| | | } |
| | | LogsFileIndexEntity entity = this.logsFile2Entity(file); |
| | | entity.setDomain(domain); |
| | | entity.setDeviceSn(deviceSn); |
| | | entity.setFileId(fileId); |
| | | |
| | | return mapper.insert(entity) > 0; |
| | | } |
| | | |
| | | @Override |
| | | public List<LogsFileUpload> getFileIndexByFileIds(List<LogsFileDTO> files) { |
| | | List<LogsFileUpload> list = new ArrayList<>(); |
| | | files.forEach(file -> { |
| | | Optional<LogsFileUpload> fileOpt = this.getFileIndexByFileId(file.getFileId()); |
| | | fileOpt.ifPresent(fileUpload -> { |
| | | fileUpload.setObjectKey(file.getStatus() ? file.getObjectKey() : ""); |
| | | list.add(fileUpload); |
| | | }); |
| | | }); |
| | | return list; |
| | | } |
| | | |
| | | @Override |
| | | public void deleteFileIndexByFileIds(List<String> fileIds) { |
| | | mapper.delete(new LambdaUpdateWrapper<LogsFileIndexEntity>() |
| | | .or(wrapper -> fileIds.forEach(fileId -> wrapper.eq(LogsFileIndexEntity::getFileId, fileId)))); |
| | | } |
| | | |
| | | @Override |
| | | public Optional<LogsFileUpload> getFileIndexByFileId(String fileId) { |
| | | List<LogsFileIndexEntity> logsFileIndexList = mapper.selectList( |
| | | new LambdaQueryWrapper<LogsFileIndexEntity>().eq(LogsFileIndexEntity::getFileId, fileId)); |
| | | if (CollectionUtils.isEmpty(logsFileIndexList)) { |
| | | return Optional.empty(); |
| | | } |
| | | LogsFileIndexEntity entity = logsFileIndexList.get(0); |
| | | List<LogsFile> logsFileList = logsFileIndexList.stream().map(this::entity2LogsFile).collect(Collectors.toList()); |
| | | return Optional.of(LogsFileUpload.builder() |
| | | .deviceSn(entity.getDeviceSn()) |
| | | .deviceModelDomain(String.valueOf(entity.getDomain())) |
| | | .list(logsFileList) |
| | | .fileId(fileId) |
| | | .build()); |
| | | |
| | | } |
| | | |
| | | private LogsFile entity2LogsFile(LogsFileIndexEntity entity) { |
| | | if (Objects.isNull(entity)) { |
| | | return null; |
| | | } |
| | | return LogsFile.builder() |
| | | .bootIndex(entity.getBootIndex()) |
| | | .startTime(entity.getStartTime()) |
| | | .endTime(entity.getEndTime()) |
| | | .size(entity.getSize()) |
| | | .build(); |
| | | |
| | | } |
| | | |
| | | private LogsFileIndexEntity logsFile2Entity(LogsFile file) { |
| | | if (Objects.isNull(file)) { |
| | | return null; |
| | | } |
| | | return LogsFileIndexEntity.builder() |
| | | .bootIndex(file.getBootIndex()) |
| | | .size(file.getSize()) |
| | | .startTime(file.getStartTime()) |
| | | .endTime(file.getEndTime()) |
| | | .build(); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dji.sample.manage.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.dji.sample.component.mqtt.model.EventsResultStatusEnum; |
| | | import com.dji.sample.component.oss.model.OssConfiguration; |
| | | import com.dji.sample.component.oss.service.impl.OssServiceContext; |
| | | import com.dji.sample.manage.dao.ILogsFileMapper; |
| | | import com.dji.sample.manage.model.dto.LogsFileDTO; |
| | | import com.dji.sample.manage.model.entity.LogsFileEntity; |
| | | import com.dji.sample.manage.model.receiver.LogsExtFileReceiver; |
| | | import com.dji.sample.manage.model.receiver.LogsFile; |
| | | import com.dji.sample.manage.model.receiver.LogsFileUpload; |
| | | import com.dji.sample.manage.service.ILogsFileIndexService; |
| | | import com.dji.sample.manage.service.ILogsFileService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.net.URL; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | import java.util.UUID; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * @author sean |
| | | * @version 1.2 |
| | | * @date 2022/9/7 |
| | | */ |
| | | @Service |
| | | @Transactional |
| | | public class LogsFileServiceImpl implements ILogsFileService { |
| | | |
| | | @Autowired |
| | | private ILogsFileMapper mapper; |
| | | |
| | | @Autowired |
| | | private ILogsFileIndexService logsFileIndexService; |
| | | |
| | | @Autowired |
| | | private OssServiceContext ossService; |
| | | |
| | | @Autowired |
| | | private OssConfiguration configuration; |
| | | |
| | | @Autowired |
| | | private OssServiceContext ossServiceContext; |
| | | |
| | | @Override |
| | | public List<LogsFileDTO> getLogsFileInfoByLogsId(String logsId) { |
| | | return mapper.selectList( |
| | | new LambdaQueryWrapper<LogsFileEntity>() |
| | | .eq(LogsFileEntity::getLogsId, logsId)).stream() |
| | | .map(this::entity2Dto).collect(Collectors.toList()); |
| | | } |
| | | |
| | | private LogsFileDTO entity2Dto(LogsFileEntity entity) { |
| | | if (Objects.isNull(entity)) { |
| | | return null; |
| | | } |
| | | return LogsFileDTO.builder() |
| | | .deviceSn(entity.getDeviceSn()) |
| | | .fileId(entity.getFileId()) |
| | | .fingerprint(entity.getFingerprint()) |
| | | .logsId(entity.getLogsId()) |
| | | .name(entity.getName()) |
| | | .objectKey(entity.getObjectKey()) |
| | | .size(entity.getSize()) |
| | | .status(entity.getStatus()) |
| | | .build(); |
| | | } |
| | | |
| | | @Override |
| | | public List<LogsFileUpload> getLogsFileByLogsId(String logsId) { |
| | | List<LogsFileDTO> logsFiles = this.getLogsFileInfoByLogsId(logsId); |
| | | if (CollectionUtils.isEmpty(logsFiles)) { |
| | | return new ArrayList<>(); |
| | | } |
| | | return logsFileIndexService.getFileIndexByFileIds(logsFiles); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean insertFile(LogsFileUpload file, String logsId) { |
| | | LogsFileEntity entity = LogsFileEntity.builder() |
| | | .logsId(logsId) |
| | | .fileId(UUID.randomUUID().toString()) |
| | | .objectKey(file.getObjectKey()) |
| | | .status(false) |
| | | .deviceSn(file.getDeviceSn()) |
| | | .build(); |
| | | boolean insert = mapper.insert(entity) > 0; |
| | | if (!insert) { |
| | | return false; |
| | | } |
| | | for (LogsFile logsFile : file.getList()) { |
| | | insert = logsFileIndexService.insertFileIndex(logsFile, file.getDeviceSn(), Integer.valueOf(file.getDeviceModelDomain()), entity.getFileId()); |
| | | if (!insert) { |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public void deleteFileByLogsId(String logsId) { |
| | | List<LogsFileDTO> logsFiles = this.getLogsFileInfoByLogsId(logsId); |
| | | if (CollectionUtils.isEmpty(logsFiles)) { |
| | | return; |
| | | } |
| | | mapper.delete(new LambdaUpdateWrapper<LogsFileEntity>().eq(LogsFileEntity::getLogsId, logsId)); |
| | | List<String> fileIds = new ArrayList<>(); |
| | | logsFiles.forEach(file -> { |
| | | if (file.getStatus()) { |
| | | ossService.deleteObject(configuration.getBucket(), file.getObjectKey()); |
| | | } |
| | | fileIds.add(file.getFileId()); |
| | | }); |
| | | |
| | | logsFileIndexService.deleteFileIndexByFileIds(fileIds); |
| | | } |
| | | |
| | | @Override |
| | | public void updateFile(String logsId, LogsExtFileReceiver fileReceiver) { |
| | | List<LogsFileDTO> logsFiles = this.getLogsFileInfoByLogsId(logsId); |
| | | if (CollectionUtils.isEmpty(logsFiles)) { |
| | | return; |
| | | } |
| | | mapper.update(receiver2Entity(fileReceiver), |
| | | new LambdaUpdateWrapper<LogsFileEntity>().eq(LogsFileEntity::getLogsId, logsId) |
| | | .eq(LogsFileEntity::getDeviceSn, fileReceiver.getDeviceSn())); |
| | | } |
| | | |
| | | @Override |
| | | public void updateFileUploadStatus(String logsId, Boolean isUploaded) { |
| | | mapper.update(LogsFileEntity.builder().status(isUploaded).build(), |
| | | new LambdaUpdateWrapper<LogsFileEntity>().eq(LogsFileEntity::getLogsId, logsId)); |
| | | } |
| | | |
| | | @Override |
| | | public URL getLogsFileUrl(String logsId, String fileId) { |
| | | LogsFileEntity logsFile = mapper.selectOne(new LambdaQueryWrapper<LogsFileEntity>() |
| | | .eq(LogsFileEntity::getLogsId, logsId).eq(LogsFileEntity::getFileId, fileId)); |
| | | if (Objects.isNull(logsFile)) { |
| | | return null; |
| | | } |
| | | return ossService.getObjectUrl(configuration.getBucket(), logsFile.getObjectKey()); |
| | | } |
| | | |
| | | private LogsFileEntity receiver2Entity(LogsExtFileReceiver receiver) { |
| | | if (Objects.isNull(receiver)) { |
| | | return null; |
| | | } |
| | | return LogsFileEntity.builder() |
| | | .fingerprint(receiver.getFingerprint()) |
| | | .size(receiver.getSize()) |
| | | .status(Objects.nonNull(receiver.getProgress()) && |
| | | EventsResultStatusEnum.OK.getDesc().equals(receiver.getProgress().getStatus())) |
| | | .name(receiver.getKey().substring(receiver.getKey().lastIndexOf("/") + 1)).build(); |
| | | } |
| | | } |
| | |
| | | |
| | | List<TopologyDTO> topologyList = new ArrayList<>(); |
| | | |
| | | gatewayList.forEach(device -> { |
| | | List<TopologyDeviceDTO> parents = new ArrayList<>(); |
| | | TopologyDeviceDTO gateway = deviceService.deviceConvertToTopologyDTO(device); |
| | | parents.add(gateway); |
| | | |
| | | // Query the topology data of the drone based on the drone sn. |
| | | Optional<TopologyDeviceDTO> deviceTopo = deviceService.getDeviceTopoForPilot(device.getChildDeviceSn()); |
| | | List<TopologyDeviceDTO> deviceTopoList = new ArrayList<>(); |
| | | deviceTopo.ifPresent(deviceTopoList::add); |
| | | |
| | | topologyList.add(TopologyDTO.builder().parents(parents).hosts(deviceTopoList).build()); |
| | | }); |
| | | gatewayList.forEach(device -> this.getDeviceTopologyByGatewaySn(device.getDeviceSn()) |
| | | .ifPresent(topologyList::add)); |
| | | |
| | | return topologyList; |
| | | } |
| | | |
| | | public Optional<TopologyDTO> getDeviceTopologyByGatewaySn(String gatewaySn) { |
| | | Optional<DeviceDTO> dtoOptional = deviceService.getDeviceBySn(gatewaySn); |
| | | if (dtoOptional.isEmpty()) { |
| | | return Optional.empty(); |
| | | } |
| | | List<TopologyDeviceDTO> parents = new ArrayList<>(); |
| | | DeviceDTO device = dtoOptional.get(); |
| | | TopologyDeviceDTO gateway = deviceService.deviceConvertToTopologyDTO(device); |
| | | parents.add(gateway); |
| | | |
| | | // Query the topology data of the drone based on the drone sn. |
| | | Optional<TopologyDeviceDTO> deviceTopo = deviceService.getDeviceTopoForPilot(device.getChildDeviceSn()); |
| | | List<TopologyDeviceDTO> deviceTopoList = new ArrayList<>(); |
| | | deviceTopo.ifPresent(deviceTopoList::add); |
| | | |
| | | return Optional.ofNullable(TopologyDTO.builder().parents(parents).hosts(deviceTopoList).build()); |
| | | } |
| | | } |
| | |
| | | groupElement.setElementType(ElementTypeEnum.findVal(elementUpdate.getContent().getGeometry().getType())); |
| | | groupElement.setColor(elementUpdate.getContent().getProperties().getColor()); |
| | | |
| | | boolean clampToGround = elementUpdate.getContent().getProperties().getClampToGround(); |
| | | Boolean clampToGround = elementUpdate.getContent().getProperties().getClampToGround(); |
| | | groupElement.setClampToGround(clampToGround); |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * Query the download address of the file according to the media file fingerprint, |
| | | * Query the download address of the file according to the media file id, |
| | | * and redirect to this address directly for download. |
| | | * @param workspaceId |
| | | * @param fingerprint |
| | | * @param fileId |
| | | * @param response |
| | | */ |
| | | @GetMapping("/{workspace_id}/file/{fingerprint}/url") |
| | | @GetMapping("/{workspace_id}/file/{file_id}/url") |
| | | public void getFileUrl(@PathVariable(name = "workspace_id") String workspaceId, |
| | | @PathVariable String fingerprint, HttpServletResponse response) { |
| | | @PathVariable(name = "file_id") String fileId, HttpServletResponse response) { |
| | | |
| | | try { |
| | | URL url = fileService.getObjectUrl(workspaceId, fingerprint); |
| | | URL url = fileService.getObjectUrl(workspaceId, fileId); |
| | | response.sendRedirect(url.toString()); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | |
| | | |
| | | private String accessKeySecret; |
| | | |
| | | private Integer expire; |
| | | private Long expire; |
| | | |
| | | private String securityToken; |
| | | |
| | | public CredentialsDTO(Credentials credentials, int expire) { |
| | | public CredentialsDTO(Credentials credentials, long expire) { |
| | | this.accessKeyId = credentials.accessKey(); |
| | | this.accessKeySecret = credentials.secretKey(); |
| | | this.securityToken = credentials.sessionToken(); |
| | |
| | | this.accessKeyId = credentials.getAccessKeyId(); |
| | | this.accessKeySecret = credentials.getAccessKeySecret(); |
| | | this.securityToken = credentials.getSecurityToken(); |
| | | this.expire = Math.toIntExact(expire); |
| | | this.expire = expire; |
| | | } |
| | | |
| | | public CredentialsDTO(com.amazonaws.services.securitytoken.model.Credentials credentials) { |
| | | this.accessKeyId = credentials.getAccessKeyId(); |
| | | this.accessKeySecret = credentials.getSecretAccessKey(); |
| | | this.securityToken = credentials.getSessionToken(); |
| | | this.expire = Math.toIntExact((credentials.getExpiration().getTime() - System.currentTimeMillis()) / 1000); |
| | | this.expire = (credentials.getExpiration().getTime() - System.currentTimeMillis()) / 1000; |
| | | } |
| | | } |
| | |
| | | @AllArgsConstructor |
| | | public class MediaFileDTO { |
| | | |
| | | private String fileId; |
| | | |
| | | private String fileName; |
| | | |
| | | private String filePath; |
| | |
| | | @TableId(type = IdType.AUTO) |
| | | private Integer id; |
| | | |
| | | @TableField("file_id") |
| | | private String fileId; |
| | | |
| | | @TableField("file_name") |
| | | private String fileName; |
| | | |
| | |
| | | /** |
| | | * Get the download address of the file. |
| | | * @param workspaceId |
| | | * @param fingerprint |
| | | * @param fileId |
| | | * @return |
| | | */ |
| | | URL getObjectUrl(String workspaceId, String fingerprint); |
| | | URL getObjectUrl(String workspaceId, String fileId); |
| | | } |
| | |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | import java.util.UUID; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | return Optional.ofNullable(fileEntity); |
| | | } |
| | | |
| | | private Optional<MediaFileEntity> getMediaByFileId(String workspaceId, String fileId) { |
| | | MediaFileEntity fileEntity = mapper.selectOne(new LambdaQueryWrapper<MediaFileEntity>() |
| | | .eq(MediaFileEntity::getWorkspaceId, workspaceId) |
| | | .eq(MediaFileEntity::getFileId, fileId)); |
| | | return Optional.ofNullable(fileEntity); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean checkExist(String workspaceId, String fingerprint) { |
| | | return this.getMediaByFingerprint(workspaceId, fingerprint).isPresent(); |
| | |
| | | public Integer saveFile(String workspaceId, FileUploadDTO file) { |
| | | MediaFileEntity fileEntity = this.fileUploadConvertToEntity(file); |
| | | fileEntity.setWorkspaceId(workspaceId); |
| | | fileEntity.setFileId(UUID.randomUUID().toString()); |
| | | return mapper.insert(fileEntity); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | @Override |
| | | public URL getObjectUrl(String workspaceId, String fingerprint) { |
| | | Optional<MediaFileEntity> mediaFileOpt = getMediaByFingerprint(workspaceId, fingerprint); |
| | | public URL getObjectUrl(String workspaceId, String fileId) { |
| | | Optional<MediaFileEntity> mediaFileOpt = getMediaByFileId(workspaceId, fileId); |
| | | if (mediaFileOpt.isEmpty()) { |
| | | throw new IllegalArgumentException("{} doesn't exist."); |
| | | } |
| | |
| | | |
| | | if (entity != null) { |
| | | builder.fileName(entity.getFileName()) |
| | | .fileId(entity.getFileId()) |
| | | .filePath(entity.getFilePath()) |
| | | .isOriginal(entity.getIsOriginal()) |
| | | .fingerprint(entity.getFingerprint()) |
| | |
| | | # enable: true |
| | | # provider: aws |
| | | # endpoint: https://s3.us-east-1.amazonaws.com |
| | | # access-key: |
| | | # secret-key: |
| | | # access-key: |
| | | # secret-key: |
| | | # expire: 3600 |
| | | # region: us-east-1 |
| | | # role-session-name: cloudApi |
| | | # role-arn: |
| | | # role-arn: |
| | | # bucket: cloudapi-bucket |
| | | # object-dir-prefix: wayline |
| | | |
| | | # MinIO is temporarily unavailable. |
| | | #oss: |
| | | # enable: false |
| | | # enable: true |
| | | # provider: minio |
| | | # endpoint: |
| | | # access-key: |
| | | # secret-key: |
| | | # bucket: |
| | | # expire: |
| | | # region: |
| | | # object-dir-prefix: |
| | | # endpoint: http://192.168.1.1:9000 |
| | | # access-key: minioadmin |
| | | # secret-key: minioadmin |
| | | # bucket: cloud-bucket |
| | | # expire: 3600 |
| | | # region: us-east-1 |
| | | # object-dir-prefix: wayline |
| | | |
| | | logging: |
| | | level: |