Skip to content

Instantly share code, notes, and snippets.

@mikaeldui
Last active December 22, 2021 18:10
Show Gist options
  • Save mikaeldui/0260d4730a0bc1d1f93770633f6967e1 to your computer and use it in GitHub Desktop.
Save mikaeldui/0260d4730a0bc1d1f93770633f6967e1 to your computer and use it in GitHub Desktop.
.NET Client for TP-Link TL-ER6020
using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage.Streams;
namespace Tplink
{
internal class TplinkClient : IDisposable
{
internal HttpClient _httpClient = new HttpClient();
public TplinkClient(Uri baseAddress)
{
_httpClient.BaseAddress = baseAddress;
Network = new TplinkClientNetwork(this);
Maintenance = new TplinkClientMaintenance(this);
}
public async Task<HttpResponseMessage> LoginAsync(string username, string password)
{
var nonce = await getNonceAsync();
var md5password = _md5(password);
var submitStrMd5 = _md5($"{md5password.ToUpper()}:{nonce}");
var request = new HttpRequestMessage(HttpMethod.Post, "logon/loginJump.htm")
{
Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{"encoded", $"{username}:{submitStrMd5.ToUpper()}"},
{"nonce", nonce },
{"URL", "../logon/loginJump.htm" }
})
};
request.Headers.Add("Referer", "http://192.168.0.1/logon/logon.htm");
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
if ((await response.Content.ReadAsStringAsync()).Contains("/userRpm/Index.htm"))
{
var indexResp = await _httpClient.GetAsync("userRpm/Index.htm");
indexResp.EnsureSuccessStatusCode();
return null;
}
throw new UnauthorizedAccessException("Couldn't login on the TL-ER6020!");
async Task<string> getNonceAsync()
{
var logonResponse = await _httpClient.GetAsync("logon/logon.htm");
var cookie = logonResponse.Headers.Single(c => c.Key == "Set-Cookie").Value.Last();
return cookie.Split("; ").First().Split('=')[1];
}
}
public TplinkClientNetwork Network { get; }
public TplinkClientMaintenance Maintenance { get; }
private string _md5(string data)
{
string strAlgName = HashAlgorithmNames.Md5;
IBuffer buffUtf8Msg = CryptographicBuffer.ConvertStringToBinary(data, BinaryStringEncoding.Utf8);
HashAlgorithmProvider objAlgProv = HashAlgorithmProvider.OpenAlgorithm(strAlgName);
IBuffer buffHash = objAlgProv.HashData(buffUtf8Msg);
if (buffHash.Length != objAlgProv.HashLength)
{
throw new Exception("There was an error creating the hash");
}
string hex = CryptographicBuffer.EncodeToHexString(buffHash);
return hex;
}
public void Dispose() => ((IDisposable)_httpClient).Dispose();
public class TplinkClientNetwork
{
internal TplinkClientNetwork(TplinkClient tplinkClient)
{
Lan = new TplinkClientNetworkLan(tplinkClient);
}
public TplinkClientNetworkLan Lan { get; }
public class TplinkClientNetworkLan
{
private readonly TplinkClient _tplinkClient;
internal TplinkClientNetworkLan(TplinkClient tplinkClient) => _tplinkClient = tplinkClient;
public async Task<dynamic[]> GetDhcpServerClientListAsync()
{
var request = new HttpRequestMessage(HttpMethod.Get, "userRpm/DhcpServer_ClientList.htm?slt_interface=0");
request.Headers.Add("Referer", "http://192.168.0.1/userRpm/Interface_LanSetting.htm");
var response = await _tplinkClient._httpClient.SendAsync(request);
var result = new List<dynamic>();
await Task.Run(async () =>
{
HtmlDocument doc = new HtmlDocument(); doc.LoadHtml(await response.Content.ReadAsStringAsync());
var jsElem = doc.DocumentNode.SelectSingleNode("//script[position()=5]");
var rows = jsElem.InnerText.Split("\n").Skip(2).SkipLast(2).Select((row, index) => new { row, index })
.GroupBy(g => g.index / 4, i => i.row);
foreach (var group in rows)
{
result.Add(new
{
HostName = group.ElementAt(0).Trim(' ', '"', ','),
MacAddress = group.ElementAt(1).Trim(' ', '"', ',').Replace('-', ':'),
IpAddress = group.ElementAt(2).Trim(' ', '"', ',')
});
}
});
return result.ToArray();
}
}
}
public class TplinkClientMaintenance
{
internal TplinkClientMaintenance(TplinkClient tplinkClient)
{
Statistics = new TplinkClientMaintenanceStatistics(tplinkClient);
}
public TplinkClientMaintenanceStatistics Statistics { get; }
public class TplinkClientMaintenanceStatistics
{
private TplinkClient _tplinkClient;
public TplinkClientMaintenanceStatistics(TplinkClient tplinkClient) => _tplinkClient = tplinkClient;
public async Task<dynamic[]> GetIpTrafficStatisticsAsync()
{
var request = new HttpRequestMessage(HttpMethod.Get, "userRpm/System_Statics.htm?ch_sta_en=1&btn_save=Save&comindex=0&direct=0");
request.Headers.Add("Referer", "http://192.168.0.1/userRpm/Monitor_bandinfo.htm");
var response = await _tplinkClient._httpClient.SendAsync(request);
var result = new List<dynamic>();
await Task.Run(async () =>
{
HtmlDocument doc = new HtmlDocument(); doc.LoadHtml(await response.Content.ReadAsStringAsync());
var jsElem = doc.DocumentNode.SelectSingleNode("//script[position()=6]");
var rows = jsElem.InnerText.Split("\n").Skip(2).SkipLast(2).Select((row, index) => new { row, index })
.GroupBy(g => g.index / 10, i => i.row);
foreach (var group in rows)
{
result.Add(new
{
IpAddress = group.ElementAt(0).Trim(' ', '"', ','),
TransmitingRateUp = decimal.Parse(group.ElementAt(8).Trim(' ', '"', ',')),
TransmitingRateDown = decimal.Parse(group.ElementAt(9).Trim(' ', '"', ',')),
PacketsRateUp = decimal.Parse(group.ElementAt(6).Trim(' ', '"', ',')),
PacketsRateDown = decimal.Parse(group.ElementAt(7).Trim(' ', '"', ',')),
TotalPacketsUp = decimal.Parse(group.ElementAt(2).Trim(' ', '"', ',')),
TotalPacketsDown = decimal.Parse(group.ElementAt(3).Trim(' ', '"', ',')),
TotalBytesUp = decimal.Parse(group.ElementAt(4).Trim(' ', '"', ',')),
TotalBytesDown = decimal.Parse(group.ElementAt(5).Trim(' ', '"', ',')),
});
}
});
return result.ToArray();
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment