-
-
Save mbentley/03c198077c81d52cb029b825e9a6dc18 to your computer and use it in GitHub Desktop.
### PowerShell Example | |
# set variables | |
$OMADA_URL = "https://omada.example.com:8043" | |
$USERNAME = "admin" | |
$PASSWORD = "test12345" | |
# get controller id from the API | |
$CONTROLLER_ID = (Invoke-RestMethod -Uri "${OMADA_URL}/api/info" -Method Get -UseBasicParsing).result.omadacId | |
# set the login request body as json | |
$loginRequestBody = @{ | |
username = $USERNAME | |
password = $PASSWORD | |
} | ConvertTo-Json | |
# login, get token, set a session variable | |
$loginResponse = Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/login" -Method Post -ContentType "application/json" -Body $loginRequestBody -SessionVariable OmadaSession | |
# extract the token and create a variable for the headers | |
$TOKEN = $loginResponse.result.token | |
$RequestHeaders = @{ | |
"Csrf-Token" = $TOKEN | |
"Content-Type" = "application/json" | |
} | |
# validate login | |
Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/loginStatus?token=${TOKEN}" -Method Get -Headers $RequestHeaders -WebSession $OmadaSession | |
# example to get info on the current user | |
Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/users/current?token=${TOKEN}¤tPage=1¤tPageSize=1000" -Method Get -Headers $RequestHeaders -WebSession $OmadaSession |
### Bash Example | |
# set variables | |
OMADA_URL="https://omada.example.com:8043" | |
USERNAME="admin" | |
PASSWORD="test12345" | |
# get controller id from the API | |
CONTROLLER_ID="$(curl -sk "${OMADA_URL}/api/info" | jq -r .result.omadacId)" | |
# login, get token, set & use cookies | |
TOKEN="$(curl -sk -X POST -c "/tmp/omada-cookies.txt" -b "/tmp/omada-cookies.txt" -H "Content-Type: application/json" "${OMADA_URL}/${CONTROLLER_ID}/api/v2/login" -d '{"username": "'"${USERNAME}"'", "password": "'"${PASSWORD}"'"}' | jq -r .result.token)" | |
# once logged in, make sure you add the following header on additional API calls: | |
# -H "Csrf-Token: ${TOKEN}" | |
# validate login | |
curl -sk -X GET -b "/tmp/omada-cookies.txt" -H "Content-Type: application/json" -H "Csrf-Token: ${TOKEN}" "${OMADA_URL}/${CONTROLLER_ID}/api/v2/loginStatus?token=${TOKEN}" | jq . | |
# example to get info on the current user | |
curl -sk -X GET -b "/tmp/omada-cookies.txt" -H "Content-Type: application/json" -H "Csrf-Token: ${TOKEN}" "${OMADA_URL}/${CONTROLLER_ID}/api/v2/users/current?token=${TOKEN}¤tPage=1¤tPageSize=1000" |
There's a new v3 API? I hadn't seen anything about that and it doesn't look like the app itself uses anything that's listed as a v3 API. Here is where the API documentation came from:
Post 27 has the API from version 5 of the controller:
https://static-community.tp-link.com/attach/8/2/2022/78d3f067ac0c491d931426e040188632.zip
That thread has the most info I've seen.
That script doesn't work for me. I'm using Python3 on Ubuntu 22.04. It gives a syntax error in line 9 at the first $.
Hard to tell without the error but do you have jq
installed?
Hi @mbentley - this post helped us a lot! Still struggeling with the API with PATCH-requests!
Would you please give me a hint how to patch my SSID? In my newbie-understanding: PATCH means change of json parameters provided on existing SSID-IDs are only updating the parameters i give with -d command in curl commands, right?
Not very familiar with the syntax, but regarding to your post it should be like this:
curl -sk -X PATCH -b "/tmp/omada-cookies.txt" -H "Content-Type: application/json" -H "Csrf-Token: ${TOKEN}" "${OMADA_URL}/$#{CONTROLLER_ID}/api/v2/sites/${SITE_ID}/setting/wlans/${WLANG_ID}/ssids/${SSID_ID}" -d '{"guestNetEnable": true}' | jq .
My output is like this:
+ curl -sk -X PATCH -b /tmp/omada-cookies.txt -H 'Content-Type: application/json' -H 'Csrf-Token: 7773437e2aac4dc0855c3e66f7a623a5' 'https://localhost:8043/0{CONTROLLER_ID}/api/v2/sites/xxx/setting/wlans/xxxx/ssids/xxxxx' -d '{guestNetEnable: true}'
+ jq .
container-logs tell me:
06-09-2023 10:05:00.061 INFO [main] [] c.t.s.o.m.d.p.b.a(): manager maintenance Handling event: org.springframework.boot.context.event.ApplicationStartedEvent[source=org.springframework.boot.SpringApplication@48ebe700] 06-09-2023 10:05:05.781 INFO [main] [] c.t.s.o.m.d.p.t.TransportConfiguration(): upgradeSendReq workGroup core thread num is 1, max thread num is 1 06-09-2023 10:05:02.940 INFO [main] [] c.t.s.o.m.d.d.m.m.c.DeviceMsgConfig(): setMsgThreadPool thread coreSize is 2, maxSize is 2,queue size is 4500 06-09-2023 12:38:18.121 INFO [https-jsse-nio-8043-exec-10] [] c.t.s.o.p.p.a.k(): Received invalid PortalBatchQueryDTO: PortalBatchQueryDTO(omadacId=c8b3f6990521069893312536078fa709, siteId=6482c7dc3b76be5b1487f19f, portalIds=[]) 06-09-2023 12:37:47.339 INFO [https-jsse-nio-8043-exec-9] [] c.t.s.o.p.p.a.k(): Received invalid PortalBatchQueryDTO: PortalBatchQueryDTO(omadacId=c8b3f6990521069893312536078fa709, siteId=6482c7dc3b76be5b1487f19f, portalIds=[]) 06-09-2023 13:12:38.017 INFO [https-jsse-nio-8043-exec-5] [] c.t.s.o.p.p.a.k(): Received invalid PortalBatchQueryDTO: PortalBatchQueryDTO(omadacId=c8b3f6990521069893312536078fa709, siteId=6482c7dc3b76be5b1487f19f, portalIds=[])
Where did you get the port from your OMADA_URL-Variable? Mine is 8043 as it is declared in the docker-compose file for the Managment-Port!? GET-requests work like charm with this :)
Thanks in advance!
The port was just a mis-type as I actually just use 443 on my own controller. It's just the https port though.
As for figuring out the APIs and what they need, I usually just try to do something in the UI and check out the API calls that the interface makes in my browser's dev tools to make sure that I am doing things right. Like what you're doing on my own network, it uses the following payload for the PATCH request:
{"name":"bentley-guest","band":3,"guestNetEnable":true,"security":0,"broadcast":true,"vlanEnable":true,"vlanId":10,"rateLimit":{"downLimitEnable":false,"upLimitEnable":false},"ssidRateLimit":{"downLimitEnable":false,"upLimitEnable":false},"wlanScheduleEnable":false,"rateAndBeaconCtrl":{"rate2gCtrlEnable":false,"rate5gCtrlEnable":false},"macFilterEnable":false,"wlanId":"","enable11r":false,"multiCastSetting":{"multiCastEnable":false,"arpCastEnable":false,"filterEnable":false,"ipv6CastEnable":false}}
So it looks like it is including more than just the one value as a more verbose curl returns:
{"errorCode":-1001,"msg":"Invalid request parameters."}
You might have to parse the response from where it looks like it's pulling the existing data from at this API endpoint: /${CONTROLLER_ID}/api/v2/sites/Default/setting/wlans/xxxxxxxx/ssids?currentPage=1¤tPageSize=10
I did a PATCH via curl with the full payload and it worked, returning {"errorCode":0,"msg":"Success."}
.
Can't tell me why I always get the following:
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- 不可以删除,用以本地版本校准静态资源路径,从根目录获取 -->
<base href="/" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="width=1300,initial-scale=1,minimal-ui"/>
<link rel="shortcut icon" href="favicon.ico"/>
<link rel="stylesheet" href="theme/lib/css/spectrum-d0fce89613.css">
<link rel="stylesheet" href="theme/css/su-a61fe7bf98.css">
<title id="title">Omada Controller</title>
<noscript>
<meta http-equiv="refresh" content="0; url=error.html"/>
</noscript>
</head>
<body>
<div id="main-container" class="m-b-0"></div>
<canvas id="canvas-test"></canvas>
<script type="text/javascript" src="js/libs/polyfill-6926951583.min.js"></script>
<script type="text/javascript" src="js/libs/g6-75b82cdd1d.min.js" async></script>
<script type="text/javascript" src="js/libs/jquery-4cb8672160.min.js"></script>
<script type="text/javascript" src="js/libs/jquery-16e37f8666.ui.min.js"></script>
<script type="text/javascript" src="js/libs/sockjs-e2b1fc0be3.min.js"></script>
<script type="text/javascript" src="js/libs/stomp-51779f8e6c.min.js"></script>
<!--<script type="text/javascript" src="js/libs/excanvas-884b8a4daa.min.js"></script>-->
<script type="text/javascript" src="js/libs/resize-observer-c32f1af8c3.min.js"></script>
<script type="text/javascript" src="js/libs/spectrum-dae9c90a3b.min.js"></script>
<script type="text/javascript" src="js/libs/jquery-202b9c1ad9.cookie.min.js"></script>
<script type="text/javascript" src="js/libs/perfect-scrollbar-85fff207d9.min.js"></script>
<script type="text/javascript" src="js/libs/lottie-cedc90aaa6.min.js"></script>
<script type="text/javascript" src="js/libs/cryptoJS-242f7a6460.min.js"></script>
<script type="text/javascript" src="js/libs/moment-761502841c.min.js"></script>
<script type="text/javascript" src="js/libs/moment-timezone-with-data-5c8ed7bc8a.min.js"></script>
<script type="text/javascript" src="js/libs/json2html-8826f30caf.min.js"></script>
<script type="text/javascript" src="js/libs/qiankun-af1f11c736.min.js"></script>
<script type="text/javascript" src="js/su/su-e7a464013a.js"></script>
<script type="text/javascript">
$.su.language = new $.su.Language();
var canvas = document.getElementById("canvas-test");
try {
canvas.getContext("2d");
document.body.removeChild(canvas);
} catch (e) {
location.href = "./error.html";
}
var WebSocketsExist = !!window.WebSocket;
if (!WebSocketsExist) {
location.href = "./error.html";
}
</script>
<script type="text/javascript" src="js/su/service-074f624000.js"></script>
<script type="text/javascript" src="js/su/data-fc10d8ee54.js"></script>
<script type="text/javascript" src="js/su/widget-665e38f169.js"></script>
<script type="text/javascript" src="js/su/form-a8aae2edd1.js"></script>
<script type="text/javascript" src="js/su/manager-a30c673f55.js"></script>
<script type="text/javascript" src="js/su/dataBind-f4e5c3f2c6.js"></script>
<script type="text/javascript" src="js/su/application-7c61407273.js"></script>
<script type="text/javascript" src="js/app/app-490d3af263.js"></script>
<script type="text/javascript">
$(document).ready(function(e){
App = new $.su.App();
App.setContainer("main-container");
App.init().done(function(){
App.launch();
});
});
</script>
</body>
</html>
Hard to tell without further detail but this is just the login page as HTML.
An example of a request:
Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/sites/Default/devices" -Method Get -ContentType "application/json" -Headers $CsrfTokenHeader -UseBasicParsing
I will have to give it a shot with PowerShell when I get a chance. I haven't done so before.
### Set variables
$OMADA_URL = "https://URL"
$USERNAME = "username"
$PASSWORD = "password"
### Get controller id from the API
$CONTROLLER_ID = (Invoke-RestMethod -Uri "${OMADA_URL}/api/info" -Method Get -UseBasicParsing).result.omadacId
### Login, get token, set & use cookies
$loginRequestBody = @{
username = $USERNAME
password = $PASSWORD
} | ConvertTo-Json
$loginResponse = Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/login" -Method Post -ContentType "application/json" -Body $loginRequestBody -SessionVariable session
$TOKEN = $loginResponse.result.token
$CsrfTokenHeader = @{
"Csrf-Token" = $TOKEN
"Content-Type" = "application/json"
}
Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/sites/Default/devices" -Method Get -ContentType "application/json" -Headers $CsrfTokenHeader -UseBasicParsing
Is this still working with the latest controller released Sep 19, 2023?
Is this still working with the latest controller released Sep 19, 2023?
Yes
@eugen257 - so the only issue with your powershell is that you set the session variable but you never use it. According to this powershell reference, you need to use -WebSession $session
to reference in in PowerShell 7.3 or older. I added a complete working example of a powershell above in the gist that matches what the bash example does.
@mbentley can you tell me how I can read all the settings and most importantly the MAC whitelist filter
It doesn't show anything useful. and the documentation also does not have a clear understanding of how to do this:
(Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/sites/638ef74e14f65e09652531f5/setting/firewall/macfilters?token=${TOKEN}" -Method Get -Headers $RequestHeaders -WebSession $OmadaSession).result
Why is the list not active here and I can’t activate it?
$macFilterConfig = @{
enable = $true
}
Invoke-RestMethod -Uri "$OMADA_URL/$OMADAC_ID/api/v2/sites/$SITE_ID/setting/firewall/macfilter" -Method Post -ContentType "application/json" -Body ($macFilterConfig | ConvertTo-Json) -Headers $RequestHeaders -UseBasicParsing -WebSession $OmadaSession
0 Success. @{enable=False}
I wrote a similar example for the new openapi . See this gist
That doesn't work for me. What works is this but I still can't find how to add devices to the whitelist:
'### PowerShell Example'
'# set variables'
'$OMADA_URL = "https://omada.local" '
'$USERNAME = "login" '
'$PASSWORD = "pass" '
'# get controller id from the API'
'$CONTROLLER_ID = (Invoke-RestMethod -Uri "${OMADA_URL}/api/info" -Method Get -UseBasicParsing).result.omadacId'
'# set the login request body as json
'$loginRequestBody = @{
username = $USERNAME
password = $PASSWORD
} | ConvertTo-Json'
'# login, get token, set a session variable'
'$loginResponse = Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/login" -Method Post -ContentType "application/json" -Body $loginRequestBody -SessionVariable OmadaSession'
'# extract the token and create a variable for the headers'
'$TOKEN = $loginResponse.result.token'
'$RequestHeaders = @{
"Csrf-Token" = $TOKEN
"Content-Type" = "application/json"
}'
'# validate login'
'Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/loginStatus?token=${TOKEN}" -Method Get -Headers $RequestHeaders -WebSession $OmadaSession'
'# example to get info on the current user'
'$CurrentUser = Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/users/current?token=${TOKEN}¤tPage=1¤tPageSize=1000" -Method Get -Headers $RequestHeaders -WebSession $OmadaSession'
'$CurrentUser.result'
'#Sitens'
'$SITE = (Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/sites?currentPage=1¤tPageSize=1000" -Method Get -Headers $RequestHeaders -WebSession $OmadaSession).result.data'
'$SITE_ID = $SITE.id'
'#devices'
'(Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/sites/${SITE_ID}/devices" -Method Get -Headers $RequestHeaders -WebSession $OmadaSession).result | select name'
'#settings'
'(Invoke-RestMethod -Uri "${OMADA_URL}/${CONTROLLER_ID}/api/v2/sites/${SITE_ID}/setting?currentPage=1¤tPageSize=1000" -Method Get -Headers $RequestHeaders -WebSession $OmadaSession).result #| select name'
Do you have one example with the new api V3 or the documentation link?