Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

318 lines
8.7 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. var websock;
  2. var password = false;
  3. // http://www.the-art-of-web.com/javascript/validate-password/
  4. function checkPassword(str) {
  5. // at least one number, one lowercase and one uppercase letter
  6. // at least eight characters that are letters, numbers or the underscore
  7. var re = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])\w{8,}$/;
  8. return re.test(str);
  9. }
  10. function validateForm() {
  11. var form = $("#formSave");
  12. // password
  13. var adminPass1 = $("input[name='adminPass1']", form).val();
  14. if (adminPass1.length > 0 && !checkPassword(adminPass1)) {
  15. alert("The password you have entered is not valid, it must have at least 8 characters, 1 lower and 1 uppercase and 1 number!");
  16. return false;
  17. }
  18. var adminPass2 = $("input[name='adminPass2']", form).val();
  19. if (adminPass1 != adminPass2) {
  20. alert("Passwords are different!");
  21. return false;
  22. }
  23. return true;
  24. }
  25. function doUpdate() {
  26. if (validateForm()) {
  27. var data = $("#formSave").serializeArray();
  28. websock.send(JSON.stringify({'config': data}));
  29. $(".powExpected").val(0);
  30. }
  31. return false;
  32. }
  33. function doReset() {
  34. var response = window.confirm("Are you sure you want to reset the device?");
  35. if (response == false) return false;
  36. websock.send(JSON.stringify({'action': 'reset'}));
  37. return false;
  38. }
  39. function doReconnect() {
  40. var response = window.confirm("Are you sure you want to disconnect from the current WIFI network?");
  41. if (response == false) return false;
  42. websock.send(JSON.stringify({'action': 'reconnect'}));
  43. return false;
  44. }
  45. function doToggle(element, value) {
  46. var relayID = parseInt(element.attr("data"));
  47. websock.send(JSON.stringify({'action': value ? 'on' : 'off', 'relayID': relayID}));
  48. return false;
  49. }
  50. function randomString(length, chars) {
  51. var mask = '';
  52. if (chars.indexOf('a') > -1) mask += 'abcdefghijklmnopqrstuvwxyz';
  53. if (chars.indexOf('A') > -1) mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  54. if (chars.indexOf('#') > -1) mask += '0123456789';
  55. if (chars.indexOf('@') > -1) mask += 'ABCDEF';
  56. if (chars.indexOf('!') > -1) mask += '~`!@#$%^&*()_+-={}[]:";\'<>?,./|\\';
  57. var result = '';
  58. for (var i = length; i > 0; --i) result += mask[Math.round(Math.random() * (mask.length - 1))];
  59. return result;
  60. }
  61. function doGenerateAPIKey() {
  62. var apikey = randomString(16, '@#');
  63. $("input[name=\"apiKey\"]").val(apikey);
  64. return false;
  65. }
  66. function showPanel() {
  67. $(".panel").hide();
  68. $("#" + $(this).attr("data")).show();
  69. if ($("#layout").hasClass('active')) toggleMenu();
  70. $("input[type='checkbox']").iphoneStyle("calculateDimensions").iphoneStyle("refresh");
  71. };
  72. function toggleMenu() {
  73. $("#layout").toggleClass('active');
  74. $("#menu").toggleClass('active');
  75. $("#menuLink").toggleClass('active');
  76. }
  77. function createRelays(count) {
  78. var current = $("#relays > div").length;
  79. if (current > 0) return;
  80. var template = $("#relayTemplate .pure-g")[0];
  81. for (var relayID=0; relayID<count; relayID++) {
  82. var line = $(template).clone();
  83. $(line).find("input").each(function() {
  84. $(this).attr("data", relayID);
  85. });
  86. if (count > 1) $(".relay_id", line).html(" " + (relayID+1));
  87. line.appendTo("#relays");
  88. $(":checkbox", line).iphoneStyle({
  89. onChange: doToggle,
  90. resizeContainer: true,
  91. resizeHandle: true,
  92. checkedLabel: 'ON',
  93. uncheckedLabel: 'OFF'
  94. });
  95. }
  96. }
  97. function createIdxs(count) {
  98. var current = $("#idxs > div").length;
  99. if (current > 0) return;
  100. var template = $("#idxTemplate .pure-g")[0];
  101. for (var id=0; id<count; id++) {
  102. var line = $(template).clone();
  103. $(line).find("input").each(function() {
  104. $(this).attr("data", id).attr("tabindex", 43+id);
  105. });
  106. if (count > 1) $(".id", line).html(" " + id);
  107. line.appendTo("#idxs");
  108. }
  109. }
  110. function processData(data) {
  111. // title
  112. if ("app" in data) {
  113. var title = data.app;
  114. if ("version" in data) {
  115. title = title + " " + data.version;
  116. }
  117. $(".pure-menu-heading").html(title);
  118. if ("hostname" in data) {
  119. title = data.hostname + " - " + title;
  120. }
  121. document.title = title;
  122. }
  123. Object.keys(data).forEach(function(key) {
  124. // Actions
  125. if (key == "action") {
  126. if (data.action == "reload") {
  127. if (password) {
  128. // Forget current authentication
  129. $.ajax({
  130. 'method': 'GET',
  131. 'url': '/',
  132. 'async': false,
  133. 'username': "logmeout",
  134. 'password': "123456",
  135. 'headers': { "Authorization": "Basic xxx" }
  136. }).done(function(data) {
  137. // If we don't get an error, we actually got an error as we expect an 401!
  138. }).fail(function(){
  139. // We expect to get an 401 Unauthorized error! In this case we are successfully
  140. // logged out and we redirect the user.
  141. window.location = "/";
  142. });
  143. }
  144. }
  145. return;
  146. }
  147. // Wifi
  148. if (key == "wifi") {
  149. var groups = $("#panel-wifi .pure-g");
  150. for (var i in data.wifi) {
  151. var wifi = data.wifi[i];
  152. Object.keys(wifi).forEach(function(key) {
  153. var id = "input[name=" + key + "]";
  154. if ($(id, groups[i]).length) $(id, groups[i]).val(wifi[key]);
  155. });
  156. };
  157. return;
  158. }
  159. // Relay status
  160. if (key == "relayStatus") {
  161. var relays = data.relayStatus;
  162. createRelays(relays.length);
  163. for (var relayID in relays) {
  164. var element = $(".relayStatus[data=" + relayID + "]");
  165. if (element.length > 0) {
  166. element
  167. .prop("checked", relays[relayID])
  168. .iphoneStyle("refresh");
  169. }
  170. }
  171. return;
  172. }
  173. // Domoticz
  174. if (key == "dczIdx") {
  175. var idxs = data.dczIdx;
  176. createIdxs(idxs.length);
  177. for (var i in idxs) {
  178. var element = $(".dczIdx[data=" + i + "]");
  179. if (element.length > 0) element.val(idxs[i]);
  180. }
  181. return;
  182. }
  183. // Messages
  184. if (key == "message") {
  185. window.alert(data.message);
  186. return;
  187. }
  188. // Enable options
  189. if (key.endsWith("Visible")) {
  190. var module = key.slice(0,-7);
  191. console.log(module);
  192. $(".module-" + module).show();
  193. return;
  194. }
  195. // Pre-process
  196. if (key == "network") {
  197. data.network = data.network.toUpperCase();
  198. }
  199. if (key == "mqttStatus") {
  200. data.mqttStatus = data.mqttStatus ? "CONNECTED" : "NOT CONNECTED";
  201. }
  202. // Look for INPUTs
  203. var element = $("input[name=" + key + "]");
  204. if (element.length > 0) {
  205. if (element.attr('type') == 'checkbox') {
  206. element
  207. .prop("checked", data[key])
  208. .iphoneStyle("refresh");
  209. } else {
  210. element.val(data[key]);
  211. }
  212. return;
  213. }
  214. // Look for SELECTs
  215. var element = $("select[name=" + key + "]");
  216. if (element.length > 0) {
  217. element.val(data[key]);
  218. return;
  219. }
  220. });
  221. // Auto generate an APIKey if none defined yet
  222. if ($("input[name='apiKey']").val() == "") {
  223. doGenerateAPIKey();
  224. }
  225. }
  226. function getJson(str) {
  227. try {
  228. return JSON.parse(str);
  229. } catch (e) {
  230. return false;
  231. }
  232. }
  233. function initWebSocket(host) {
  234. if (host === undefined) {
  235. host = window.location.hostname;
  236. }
  237. websock = new WebSocket('ws://' + host + '/ws');
  238. websock.onopen = function(evt) {};
  239. websock.onclose = function(evt) {};
  240. websock.onerror = function(evt) {};
  241. websock.onmessage = function(evt) {
  242. var data = getJson(evt.data);
  243. if (data) processData(data);
  244. };
  245. }
  246. function init() {
  247. $("#menuLink").on('click', toggleMenu);
  248. $(".button-update").on('click', doUpdate);
  249. $(".button-reset").on('click', doReset);
  250. $(".button-reconnect").on('click', doReconnect);
  251. $(".button-apikey").on('click', doGenerateAPIKey);
  252. $(".pure-menu-link").on('click', showPanel);
  253. $.ajax({
  254. 'method': 'GET',
  255. 'url': '/auth'
  256. }).done(function(data) {
  257. initWebSocket();
  258. });
  259. }
  260. $(init);