code.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. // First, checks if it isn't implemented yet.
  2. if (!String.prototype.format) {
  3. String.prototype.format = function() {
  4. var args = arguments;
  5. return this.replace(/{(\d+)}/g, function(match, number) {
  6. return typeof args[number] != 'undefined'
  7. ? args[number]
  8. : match
  9. ;
  10. });
  11. };
  12. }
  13. var apList = null;
  14. var selectedSSID = "";
  15. var refreshAPInterval = null;
  16. var checkStatusInterval = null;
  17. var checkConfigInterval = null;
  18. var StatusIntervalActive = false;
  19. var ConfigIntervalActive = false;
  20. var RefreshAPIIntervalActive = false;
  21. function stopCheckStatusInterval(){
  22. if(checkStatusInterval != null){
  23. clearTimeout(checkStatusInterval);
  24. checkStatusInterval = null;
  25. }
  26. StatusIntervalActive = false;
  27. }
  28. function stopCheckConfigInterval(){
  29. if(checkConfigInterval != null){
  30. clearTimeout(checkConfigInterval);
  31. checkConfigInterval = null;
  32. }
  33. ConfigIntervalActive=false;
  34. }
  35. function stopRefreshAPInterval(){
  36. if(refreshAPInterval != null){
  37. clearTimeout(refreshAPInterval);
  38. refreshAPInterval = null;
  39. }
  40. RefreshAPIIntervalActive = false;
  41. }
  42. function startCheckStatusInterval(){
  43. StatusIntervalActive = true;
  44. checkStatusInterval = setTimeout(checkStatus, 950);
  45. }
  46. function startCheckConfigInterval(){
  47. ConfigIntervalActive = true;
  48. checkConfigInterval = setTimeout(checkConfig, 950);
  49. }
  50. function startRefreshAPInterval(){
  51. RefreshAPIIntervalActive = true;
  52. refreshAPInterval = setTimeout(refreshAP, 2800);
  53. }
  54. function RepeatCheckStatusInterval(){
  55. if(StatusIntervalActive)
  56. startCheckStatusInterval();
  57. }
  58. function RepeatCheckConfigInterval(){
  59. if(ConfigIntervalActive)
  60. startCheckConfigInterval();
  61. }
  62. function RepeatRefreshAPInterval(){
  63. if(RefreshAPIIntervalActive)
  64. startRefreshAPInterval()
  65. }
  66. $(document).ready(function(){
  67. $("#wifi-status").on("click", ".ape", function() {
  68. $( "#wifi" ).slideUp( "fast", function() {});
  69. $( "#connect-details" ).slideDown( "fast", function() {});
  70. });
  71. $("#manual_add").on("click", ".ape", function() {
  72. selectedSSID = $(this).text();
  73. $( "#ssid-pwd" ).text(selectedSSID);
  74. $( "#wifi" ).slideUp( "fast", function() {});
  75. $( "#connect_manual" ).slideDown( "fast", function() {});
  76. $( "#connect" ).slideUp( "fast", function() {});
  77. //update wait screen
  78. $( "#loading" ).show();
  79. $( "#connect-success" ).hide();
  80. $( "#connect-fail" ).hide();
  81. });
  82. $("#wifi-list").on("click", ".ape", function() {
  83. selectedSSID = $(this).text();
  84. $( "#ssid-pwd" ).text(selectedSSID);
  85. $( "#wifi" ).slideUp( "fast", function() {});
  86. $( "#connect_manual" ).slideUp( "fast", function() {});
  87. $( "#connect" ).slideDown( "fast", function() {});
  88. //update wait screen
  89. $( "#loading" ).show();
  90. $( "#connect-success" ).hide();
  91. $( "#connect-fail" ).hide();
  92. });
  93. $("#cancel").on("click", function() {
  94. selectedSSID = "";
  95. $( "#connect" ).slideUp( "fast", function() {});
  96. $( "#connect_manual" ).slideUp( "fast", function() {});
  97. $( "#wifi" ).slideDown( "fast", function() {});
  98. });
  99. $("#manual_cancel").on("click", function() {
  100. selectedSSID = "";
  101. $( "#connect" ).slideUp( "fast", function() {});
  102. $( "#connect_manual" ).slideUp( "fast", function() {});
  103. $( "#wifi" ).slideDown( "fast", function() {});
  104. });
  105. $("#join").on("click", function() {
  106. performConnect();
  107. });
  108. $("#manual_join").on("click", function() {
  109. performConnect($(this).data('connect'));
  110. });
  111. $("#ok-details").on("click", function() {
  112. $( "#connect-details" ).slideUp( "fast", function() {});
  113. $( "#wifi" ).slideDown( "fast", function() {});
  114. });
  115. $("#update").on("click", function() {
  116. performUpdate();
  117. });
  118. $("#factory").on("click", function() {
  119. performFactory();
  120. });
  121. $("#ok-credits").on("click", function() {
  122. $( "#credits" ).slideUp( "fast", function() {});
  123. $( "#app" ).slideDown( "fast", function() {});
  124. });
  125. $("#acredits").on("click", function(event) {
  126. event.preventDefault();
  127. $( "#app" ).slideUp( "fast", function() {});
  128. $( "#credits" ).slideDown( "fast", function() {});
  129. });
  130. $("#ok-connect").on("click", function() {
  131. $( "#connect-wait" ).slideUp( "fast", function() {});
  132. $( "#wifi" ).slideDown( "fast", function() {});
  133. });
  134. $("#disconnect").on("click", function() {
  135. $( "#connect-details-wrap" ).addClass('blur');
  136. $( "#diag-disconnect" ).slideDown( "fast", function() {});
  137. });
  138. $("#no-disconnect").on("click", function() {
  139. $( "#diag-disconnect" ).slideUp( "fast", function() {});
  140. $( "#connect-details-wrap" ).removeClass('blur');
  141. });
  142. $("#yes-disconnect").on("click", function() {
  143. stopCheckStatusInterval();
  144. selectedSSID = "";
  145. $( "#diag-disconnect" ).slideUp( "fast", function() {});
  146. $( "#connect-details-wrap" ).removeClass('blur');
  147. $.ajax({
  148. url: '/connect.json',
  149. dataType: 'json',
  150. method: 'DELETE',
  151. cache: false,
  152. data: { 'timestamp': Date.now()}
  153. });
  154. startCheckStatusInterval();
  155. $( "#connect-details" ).slideUp( "fast", function() {});
  156. $( "#wifi" ).slideDown( "fast", function() {})
  157. });
  158. //first time the page loads: attempt get the connection status and start the wifi scan
  159. refreshAP();
  160. startCheckStatusInterval();
  161. startRefreshAPInterval();
  162. startCheckConfigInterval();
  163. });
  164. function performUpdate(){
  165. autoexec1 = $("#autoexec1").val();
  166. //reset connection
  167. //
  168. // $( "#ok-connect" ).prop("disabled",true);
  169. // $( "#ssid-wait" ).text(selectedSSID);
  170. // $( "#connect" ).slideUp( "fast", function() {});
  171. // $( "#connect_manual" ).slideUp( "fast", function() {});
  172. // $( "#connect-wait" ).slideDown( "fast", function() {});
  173. // // todo: should we update the UI here?
  174. $.ajax({
  175. url: '/config.json',
  176. dataType: 'json',
  177. method: 'POST',
  178. cache: false,
  179. headers: { 'X-Custom-autoexec1': autoexec1 },
  180. data: { 'timestamp': Date.now()}
  181. });
  182. }
  183. function performFactory(){
  184. // $( "#ok-connect" ).prop("disabled",true);
  185. // $( "#ssid-wait" ).text(selectedSSID);
  186. // $( "#connect" ).slideUp( "fast", function() {});
  187. // $( "#connect_manual" ).slideUp( "fast", function() {});
  188. // $( "#connect-wait" ).slideDown( "fast", function() {});
  189. // // todo: should we update the UI here?
  190. $.ajax({
  191. url: '/factory.json',
  192. dataType: 'json',
  193. method: 'POST',
  194. cache: false,
  195. data: { 'timestamp': Date.now()}
  196. });
  197. }
  198. function performConnect(conntype){
  199. //stop the status refresh. This prevents a race condition where a status
  200. //request would be refreshed with wrong ip info from a previous connection
  201. //and the request would automatically shows as succesful.
  202. stopCheckStatusInterval();
  203. //stop refreshing wifi list
  204. stopRefreshAPInterval();
  205. var pwd;
  206. if (conntype == 'manual') {
  207. //Grab the manual SSID and PWD
  208. selectedSSID=$('#manual_ssid').val();
  209. pwd = $("#manual_pwd").val();
  210. }else{
  211. pwd = $("#pwd").val();
  212. }
  213. //reset connection
  214. $( "#loading" ).show();
  215. $( "#connect-success" ).hide();
  216. $( "#connect-fail" ).hide();
  217. $( "#ok-connect" ).prop("disabled",true);
  218. $( "#ssid-wait" ).text(selectedSSID);
  219. $( "#connect" ).slideUp( "fast", function() {});
  220. $( "#connect_manual" ).slideUp( "fast", function() {});
  221. $( "#connect-wait" ).slideDown( "fast", function() {});
  222. $.ajax({
  223. url: '/connect.json',
  224. dataType: 'json',
  225. method: 'POST',
  226. cache: false,
  227. headers: { 'X-Custom-ssid': selectedSSID, 'X-Custom-pwd': pwd },
  228. data: { 'timestamp': Date.now()}
  229. });
  230. //now we can re-set the intervals regardless of result
  231. startCheckStatusInterval();
  232. startRefreshAPInterval();
  233. }
  234. function rssiToIcon(rssi){
  235. if(rssi >= -60){
  236. return 'w0';
  237. }
  238. else if(rssi >= -67){
  239. return 'w1';
  240. }
  241. else if(rssi >= -75){
  242. return 'w2';
  243. }
  244. else{
  245. return 'w3';
  246. }
  247. }
  248. function refreshAP(){
  249. $.getJSON( "/ap.json", function( data ) {
  250. if(data.length > 0){
  251. //sort by signal strength
  252. data.sort(function (a, b) {
  253. var x = a["rssi"]; var y = b["rssi"];
  254. return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  255. });
  256. apList = data;
  257. refreshAPHTML(apList);
  258. }
  259. });
  260. RepeatRefreshAPInterval();
  261. }
  262. function refreshAPHTML(data){
  263. var h = "";
  264. data.forEach(function(e, idx, array) {
  265. h += '<div class="ape{0}"><div class="{1}"><div class="{2}">{3}</div></div></div>'.format(idx === array.length - 1?'':' brdb', rssiToIcon(e.rssi), e.auth==0?'':'pw',e.ssid);
  266. h += "\n";
  267. });
  268. $( "#wifi-list" ).html(h)
  269. }
  270. function checkStatus(){
  271. $.getJSON( "/status.json", function( data ) {
  272. if(data.hasOwnProperty('autoexec1') && data['autoexec1'] != ""){
  273. $("#autoexec1_current").text(data["autoexec1"]);
  274. }
  275. if(data.hasOwnProperty('ssid') && data['ssid'] != ""){
  276. if(data["ssid"] === selectedSSID){
  277. //that's a connection attempt
  278. if(data["urc"] === 0){
  279. //got connection
  280. $("#connected-to span").text(data["ssid"]);
  281. $("#connect-details h1").text(data["ssid"]);
  282. $("#ip").text(data["ip"]);
  283. $("#netmask").text(data["netmask"]);
  284. $("#gw").text(data["gw"]);
  285. $("#wifi-status").slideDown( "fast", function() {});
  286. //unlock the wait screen if needed
  287. $( "#ok-connect" ).prop("disabled",false);
  288. //update wait screen
  289. $( "#loading" ).hide();
  290. $( "#connect-success" ).show();
  291. $( "#connect-fail" ).hide();
  292. }
  293. else if(data["urc"] === 1){
  294. //failed attempt
  295. $("#connected-to span").text('');
  296. $("#connect-details h1").text('');
  297. $("#ip").text('0.0.0.0');
  298. $("#netmask").text('0.0.0.0');
  299. $("#gw").text('0.0.0.0');
  300. //don't show any connection
  301. $("#wifi-status").slideUp( "fast", function() {});
  302. //unlock the wait screen
  303. $( "#ok-connect" ).prop("disabled",false);
  304. //update wait screen
  305. $( "#loading" ).hide();
  306. $( "#connect-fail" ).show();
  307. $( "#connect-success" ).hide();
  308. }
  309. }
  310. else if(data.hasOwnProperty('urc') && data['urc'] === 0){
  311. //ESP32 is already connected to a wifi without having the user do anything
  312. if( !($("#wifi-status").is(":visible")) ){
  313. $("#connected-to span").text(data["ssid"]);
  314. $("#connect-details h1").text(data["ssid"]);
  315. $("#ip").text(data["ip"]);
  316. $("#netmask").text(data["netmask"]);
  317. $("#gw").text(data["gw"]);
  318. $("#wifi-status").slideDown( "fast", function() {});
  319. }
  320. }
  321. }
  322. else if(data.hasOwnProperty('urc') && data['urc'] === 2){
  323. //that's a manual disconnect
  324. if($("#wifi-status").is(":visible")){
  325. $("#wifi-status").slideUp( "fast", function() {});
  326. }
  327. }
  328. })
  329. .fail(function() {
  330. //don't do anything, the server might be down while esp32 recalibrates radio
  331. });
  332. RepeatCheckStatusInterval();
  333. }
  334. function checkConfig(){
  335. var h = "";
  336. //{ "autoexec" : 0, "list" : [{ 'autoexec1' : 'squeezelite -o "I2S" -b 500:2000 -d all=info -M esp32' }]}
  337. $.getJSON( "/config.json", function( data ) {
  338. if(data.hasOwnProperty('autoexec')) {
  339. h+= '<div id="autoexec">Autoexec: {0}</div>'.format(data["autoexec"]===1?"Active":"Inactive");
  340. }
  341. if(data.hasOwnProperty('list')) {
  342. data["list"].forEach(function(e, idx, array) {
  343. for (const [key, value] of Object.entries(e)) {
  344. h+= '<input id="{0}" type="text" maxlength="201" value="{1}"><br>'.format(key,value);
  345. }
  346. }
  347. );
  348. h += "\n";
  349. $( "#command-list" ).html(h);
  350. }
  351. })
  352. .fail(function() {
  353. //don't do anything, the server might be down while esp32 recalibrates radio
  354. });
  355. RepeatCheckConfigInterval();
  356. }