webmarlin-class.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. var wmEnums = {
  2. Panels : { STATUS:0, CONTROLS:1, FILES:2, CONSOLE:3 },
  3. ConsoleDirection : { APPEND:0, PREPEND:1 },
  4. ConsoleLevels : { ERROR:0, SUCCESS:1, INFO:2, MONITOR:3, WARNING:4},
  5. WSMsgDirection : { SENT:0, RECEIVED:1 },
  6. WsMsgSymbols : { SENT:{LETTER:"S",ICON:null}, RECEIVED:{LETTER:"R",ICON:null} },
  7. WSSatuses : { CONNECTING:0, OPEN:1, CLOSING:2, CLOSED:3 },
  8. LogLevels : { INFO:0, WARNING:1, ERROR:2, DEBUG:3, VERBOSE:4},
  9. TempUnits : { CELSIUS: {LABEL:"Celsius",VALUE:0,GP:"C"}, FAHRENHEIT:{LABEL:"Fahrenheit",VALUE:1,GP:"F"}, KELVIN:{LABEL:"Kelvin",VALUE:2,GP:"K"} }
  10. };
  11. var wmSettings = {
  12. AppName: "Marlin WebUI",
  13. AppRelease: "January, 1 2020",
  14. AppVersion: "1.1",
  15. AutoConnect: false,
  16. ConsoleDirection: wmEnums.ConsoleDirection.PREPEND,
  17. DefaultPanel: wmEnums.Panels.CONTROLS,
  18. LogLevel: wmEnums.LogLevels.VERBOSE,
  19. SymbolMode: 'letter',
  20. SymbolSend: wmEnums.WsMsgSymbols.SENT.LETTER,
  21. SymbolReceive: wmEnums.WsMsgSymbols.RECEIVED.LETTER,
  22. AutoTempInterval: 1,
  23. TempUnit: wmEnums.TempUnits.CELSIUS
  24. };
  25. class wmLogItem {
  26. constructor(text, mdir, mrs, gcmd=null, bgclass=null, ficon=null) {
  27. this.DateTime = wmTools.GetDateTime();
  28. this.Text = text;
  29. this.Direction = mdir;
  30. this.RsType = mrs;
  31. this.GCode = gcmd;
  32. this.BgClass = bgclass === null ? 'console-list-items-info': bgclass;
  33. this.FontIcon = ficon === null ? wmIcons.InfoCircle : ficon;
  34. this.SdFile = null;
  35. }
  36. SetValues(text=null, mdir=null, mrs=null, gcmd=null, bgclass=null, ficon=null) {
  37. if(text !== null) { this.Text = text; };
  38. if(mdir !== null) { this.Direction = mdir; };
  39. if(mrs !== null) { this.RsType = mrs; };
  40. if(gcmd !== null) { this.GCode = gcmd; };
  41. if(bgclass !== null) { this.BgClass = bgclass; };
  42. if(ficon !== null) { this.FontIcon = ficon; };
  43. }
  44. ToJson() { return JSON.stringify(this); }
  45. ToCsv() { return wmTools.StringFormatCsv(this); }
  46. ToString() { return wmTools.Stringfy(this); }
  47. ToLoglist(){
  48. switch (this.RsType) {
  49. case wmEnums.ConsoleLevels.INFO:
  50. this.BgClass = "console-list-items-info";
  51. this.FontIcon = wmIcons.InfoCircle;
  52. break;
  53. case wmEnums.ConsoleLevels.SUCCESS:
  54. this.BgClass = "console-list-items-success";
  55. this.FontIcon = wmIcons.CheckSquare;
  56. break;
  57. case wmEnums.ConsoleLevels.ERROR:
  58. this.BgClass = "console-list-items-error";
  59. this.FontIcon = wmIcons.Triangle;
  60. break;
  61. case wmEnums.ConsoleLevels.MONITOR:
  62. this.BgClass = "console-list-items-terminal";
  63. this.FontIcon = wmIcons.Terminal;
  64. break;
  65. case wmEnums.ConsoleLevels.WARNING:
  66. this.BgClass = "console-list-items-warning";
  67. this.FontIcon = wmIcons.Triangle;
  68. break;
  69. }
  70. let strout = '<li class="list-group-item console-list-items '+this.BgClass+'">';
  71. strout += '<span class="badge badge-light mr-1">'+this.FontIcon.ToHtml()+"</span>";
  72. strout += '<span class="badge badge-secondary mr-1">'+this.DateTime+'</span>';
  73. strout += '<span class="badge badge-'+(this.Direction === wmEnums.WSMsgDirection.SENT ? "danger" : "success")+' mr-1">';
  74. strout += this.Direction === wmEnums.WSMsgDirection.SENT ? wmSettings.SymbolSend : wmSettings.SymbolReceive;
  75. strout += '</span>' + this.Text + '</li>';
  76. return strout;
  77. }
  78. ToSdFileList() {
  79. if(this.SdFile !== "Begin file list" && this.SdFile !== "End file list") {
  80. let a = this.SdFile.split(" ");
  81. let strout = '<a href="javascript:void(0);" class="list-group-item list-group-item-action list-group-item-light p-1" data-sdfile="'+a[0]+'" onclick="WmButtons.SetSdSelected(this)">';
  82. strout += '<i class="icon icon-file mr-1"></i>'+a[0]+'<div class="badge badge-secondary float-right">'+wmTools.FileSizeFormat(a[1])+'</div>';
  83. strout += '</a>';
  84. return strout;
  85. }
  86. }
  87. static ParseWsMessage(msg) {
  88. let li = new wmLogItem();
  89. li.Direction = wmEnums.WSMsgDirection.RECEIVED;
  90. li.RsType = wmEnums.ConsoleLevels.SUCCESS;
  91. if (msg === "ok") {
  92. jsLog.Debug("WSMessage match: ok => " + msg);
  93. li.Text = "Acknowledge: "+msg;
  94. }
  95. else if (msg === "Not SD printing") {
  96. jsLog.Debug("WSMessage match: " + msg);
  97. li.Text = "Ack: "+msg;
  98. WmControls.SetPrinterStatusInfo(false, msg);
  99. }
  100. else if (msg.substring(0, 5) === "echo:") {
  101. if (msg.substring(5, 21) === "busy: processing") {
  102. jsLog.Debug("WSMessage match: echo:busy: processing: => " + msg);
  103. li.Text = msg.substring(5, msg.length);
  104. li.RsType = wmEnums.ConsoleLevels.WARNING;
  105. }
  106. else if (msg.substring(5, 21) === "Unknown command:") {
  107. jsLog.Debug("WSMessage match: echo:Unknown command: => " + msg);
  108. li.Text = msg.substring(5, msg.length);
  109. li.RsType = wmEnums.ConsoleLevels.WARNING;
  110. }
  111. else if (msg.substring(5,20) === "Now fresh file:") {
  112. jsLog.Debug("WSMessage match: echo:Now fresh file: => " + msg);
  113. li.Text = "SD: "+msg.substring(5, msg.length);
  114. }
  115. else if (msg==="File selected") {
  116. jsLog.Debug("WSMessage match: echo:File selected: => " + msg);
  117. li.Text = "SD: "+msg.substring(5, msg.length);
  118. }
  119. }
  120. else if (msg.substring(0, 6) === "Error:") {
  121. jsLog.Debug("WSMessage match: error => " + msg);
  122. li.Text = msg.substring(6, msg.length);
  123. li.RsType = wmEnums.ConsoleLevels.ERROR;
  124. }
  125. else if (msg.substring(0, 12) === "File opened:" || msg === "File selected") {
  126. jsLog.Debug("WSMessage match: File opened/selected => " + msg);
  127. li.Text = "SD: "+msg;
  128. }
  129. else if (msg.includes("open failed, File:")) {
  130. jsLog.Error("WSMessage match: open file error => " + msg);
  131. li.Text = "SD Error: "+msg;
  132. li.RsType = wmEnums.ConsoleLevels.ERROR;
  133. }
  134. else if (msg.toLowerCase().includes(".gco") || msg.toLowerCase().includes(".gcode") || msg.toLowerCase().includes(".g") || msg==="Begin file list" || msg==="End file list") {
  135. if(msg.substring(0,16)==="Writing to file:") { WmUpload.ReadyToWrite = true; }
  136. li.Text = "SD: "+msg;
  137. li.SdFile = msg;
  138. }
  139. //else if() {
  140. //}
  141. else {
  142. let rgx_rtemp_eb = /^T:\d{1,3}\.\d{1,2}\s+\/\d{1,3}\.\d{1,2}\s+B:\d{1,3}\.\d{1,2}\s+\/\d{1,3}\.\d{1,2}/;
  143. let rgx_rtemp_e = /^T:\d{1,3}\.\d{1,2}\s+\/\d{1,3}\.\d{1,2}/;
  144. if(rgx_rtemp_eb.test(msg) || rgx_rtemp_e.test(msg)){
  145. jsLog.Verbose("Extruder temperatore report: "+msg);
  146. msg = msg.replace(/\//g,"");
  147. let tarr = msg.split(/\s/);
  148. WmCharts.SetTempReport(tarr);
  149. li.Text = "Temp report: "+msg;
  150. }
  151. else { li.Text = msg; }
  152. }
  153. jsLog.Verbose(li.ToString());
  154. return li;
  155. }
  156. }
  157. class wmGCommandItem {
  158. constructor(g,p,v,d,s=null) {
  159. this.GCode = g;
  160. this.GParams = p;
  161. this.Values = v;
  162. this.Description = d;
  163. this.Supported = s===null ? true : s;
  164. }
  165. ToJson() { return JSON.stringify(this); }
  166. ToString() { return wmTools.Stringfy(this); }
  167. static CalcChecksum(gc) {
  168. let cs = 0;
  169. gc = gc.toUpperCase().replace(/\s/g, '');
  170. for(let i=0; gc[i]!=='*' && gc[i]!==null && i<gc.length; i++) { cs = cs ^ gc.charCodeAt(i); }
  171. jsLog.Verbose("Calculate GCommand checksum of: "+gc+" => "+cs);
  172. return cs;
  173. }
  174. static GetCommandItemByCode(gc) {
  175. jsLog.Verbose("GetCommandItemByCode: Find preset for: "+gc);
  176. let sgc = gc.split(/\s/);
  177. jsLog.Verbose("GetCommandItemByCode: Command to find: "+sgc[0]);
  178. for (let [k, v] of Object.entries(wmGCommands)) {
  179. if(v.GCode.indexOf(sgc[0]) > -1) { return v; }
  180. }
  181. return null;
  182. }
  183. }
  184. class wmFontIcon {
  185. constructor(ico, mc = null) {
  186. this.ico = ico;
  187. this.mClass = mc !== null ? " "+mc : "";
  188. }
  189. ToString() { return wmTools.Stringfy(this); }
  190. ToHtml() { return "<i class=\"icon icon-"+ this.ico + this.mClass+"\"></i>"; }
  191. AddClass(acl) { return "<i class=\"icon icon-"+ this.ico + " "+ acl+"\"></i>"; }
  192. }
  193. class wmTools {
  194. static Stringfy(obj) {
  195. if(obj !== null && obj !== "undefined") {
  196. let rt = "";
  197. for (let [k, v] of Object.entries(obj)) { rt += `${k}=${v};`; }
  198. return rt;
  199. } else {
  200. return obj;
  201. }
  202. }
  203. static StringFormat() {
  204. var args = Array.prototype.slice.call(arguments, 1);
  205. return arguments[0].replace(/\{(\d+)\}/g, function (match, index) { return args[index]; });
  206. }
  207. static StringFormatJson(str) {
  208. return JSON.stringify(str);
  209. }
  210. static StringFormatCsv(obj) {
  211. let rt = "";
  212. for (let [k, v] of Object.entries(obj)) { rt += `${v},`; }
  213. return rt;
  214. }
  215. static StringRemoveSpecials(str) {
  216. var spc = [".","~","{","}"];
  217. for (var i=0; i<spc.length; i++) { str = str.replace(spc[i],""); }
  218. return str;
  219. }
  220. static FileDownload(fname, ftype, fdata){
  221. var blob = new Blob(fdata, {type: ftype});
  222. window.saveAs(blob, fname);
  223. }
  224. static FileSizeFormat(size) {
  225. if(size>0) {
  226. var i = Math.floor( Math.log(size) / Math.log(1000) );
  227. return ( size / Math.pow(1000, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
  228. } else {
  229. return size+" B";
  230. }
  231. }
  232. static EscapeHtml(unsafe) {
  233. unsafe = unsafe.replace(/&/g, "&amp;");
  234. unsafe = unsafe.replace(/</g, "&lt;");
  235. unsafe = unsafe.replace(/>/g, "&gt;");
  236. unsafe = unsafe.replace(/"/g, "&quot;");
  237. unsafe = unsafe.replace(/'/g, "&#039;");
  238. return unsafe;
  239. }
  240. static GetDateTime() {
  241. var dt = new Date();
  242. var hr = dt.getHours() < 10 ? "0" + dt.getHours() : dt.getHours();
  243. var mn = dt.getMinutes() < 10 ? "0" + dt.getMinutes() : dt.getMinutes();
  244. var sc = dt.getSeconds() < 10 ? "0" + dt.getSeconds() : dt.getSeconds();
  245. return hr + ":" + mn + ":" + sc;
  246. }
  247. static GetBrowser() {
  248. return $.browser.name+" v"+$.browser.versionNumber+" on "+$.browser.platform;
  249. }
  250. static GetScreenSize() {
  251. let bwsize = "Viewport="+$(window).width()+"x"+$(window).height();
  252. bwsize += " Document="+$(document).width()+"x"+$(document).height();
  253. bwsize += " Screen="+window.screen.width+"x"+window.screen.height;
  254. return bwsize;
  255. }
  256. static GetNumPercent(p,n) {
  257. return (p / 100) * n;
  258. }
  259. static GetPercentage(p,n) {
  260. return (p * 100) / n;
  261. }
  262. static FormatNumber(v,d) {
  263. v = parseFloat(v);
  264. return v.toFixed(d).toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1.');
  265. }
  266. static CelsiusToFahrenheit(n) {
  267. return n * 9 / 5 + 32;
  268. }
  269. static CelsiusToKelvin(n) {
  270. return n+273.15;
  271. }
  272. }
  273. class wmCookie {
  274. static Read(cname) {
  275. let decCookie = decodeURIComponent(document.cookie);
  276. let carr = decCookie.split(';');
  277. for (let i=0; i<carr.length; i++) {
  278. while (carr[i].charAt(0)===' ') { carr[i] = carr[i].substring(1); }
  279. if (carr[i].indexOf(cname)===0) {
  280. let r = carr[i].substring(cname.length+1, carr[i].length);
  281. jsLog.Verbose("Load cookie '"+cname+"' => "+r);
  282. return r;
  283. }
  284. }
  285. return null;
  286. }
  287. static Write(cvalue, cname=null) {
  288. let d = new Date();
  289. d.setTime(d.getTime() + (365 * 24 * 60 * 60 * 1000));
  290. let expires = "expires=" + d.toGMTString();
  291. let cn = cname === null ? "E4dWUI" : cname;
  292. let cv = cn+ "=" + escape(cvalue) + "; " + expires + ";path=/; SameSite=None; Secure;";
  293. document.cookie = cv;
  294. jsLog.Verbose("Add/Update cookie => "+cv);
  295. }
  296. static CheckBrowser() {
  297. wmCookie.Write('1','check_browser_cookie');
  298. return (document.cookie.indexOf('check_browser_cookie') !== -1) ? true : false;
  299. }
  300. static Check() {
  301. jsLog.Verbose("Checking for browser supported cookie");
  302. if(wmCookie.CheckBrowser()===true) {
  303. jsLog.Debug("Cookies supported. Looking for custom settings");
  304. var cStr = wmCookie.Read("E4dWUI");
  305. if(cStr === null){
  306. jsLog.Verbose("No settings cookie found. Define defaults");
  307. wmCookie.Write(JSON.stringify(wmSettings));
  308. } else {
  309. jsLog.Debug("Settings cookie found. Loading customized settings");
  310. var cv = JSON.parse(cStr);
  311. wmSettings.AutoConnect = cv.AutoConnect;
  312. wmSettings.DefaultPanel = cv.DefaultPanel;
  313. wmSettings.ConsoleDirection = cv.ConsoleDirection;
  314. wmSettings.LogLevel = cv.LogLevel;
  315. wmSettings.SymbolMode = cv.SymbolMode,
  316. jsLog.Verbose("Customized cookie stored settings loaded");
  317. jsLog.Verbose(wmTools.Stringfy(wmSettings));
  318. }
  319. } else {
  320. jsLog.Warning("Cookies are not supported by the browser. Use default settings");
  321. }
  322. }
  323. }
  324. class jsLog {
  325. static Info(logmsg) {
  326. if(wmSettings.LogLevel >= wmEnums.LogLevels.INFO) { console.log("[INFO ] "+logmsg); }
  327. }
  328. static Warning(logmsg) {
  329. if(wmSettings.LogLevel >= wmEnums.LogLevels.WARNING) { console.log("[WARN ] "+logmsg); }
  330. }
  331. static Error(logmsg) {
  332. if(wmSettings.LogLevel >= wmEnums.LogLevels.ERROR) { console.log("[ERROR ] "+logmsg); }
  333. }
  334. static Debug(logmsg) {
  335. if(wmSettings.LogLevel >= wmEnums.LogLevels.DEBUG) { console.log("[DEBUG ] "+logmsg); }
  336. }
  337. static Verbose(logmsg) {
  338. if(wmSettings.LogLevel >= wmEnums.LogLevels.VERBOSE) { console.log("[VERBOSE] "+logmsg); }
  339. }
  340. }
  341. var wmGCommands = {
  342. CustomCmd : new wmGCommandItem('',null,null,'Custom command'),
  343. MoveFw : new wmGCommandItem('G1','Y{0}',10,'Move Y forward'),
  344. MoveBw : new wmGCommandItem('G1','Y-{0}',10,'Move Y backward'),
  345. MoveSx : new wmGCommandItem('G1','X{0}',10,'Move X left'),
  346. MoveDx : new wmGCommandItem('G1','X-{0}',10,'Move X right'),
  347. MoveUp : new wmGCommandItem('G1','Z{0}',10,'Move Z up'),
  348. MoveDw : new wmGCommandItem('G1','Z-{0}',10,'Move Z down'),
  349. FillRetrive : new wmGCommandItem('G10',null,null,'Retract filament'),
  350. FillExtrude : new wmGCommandItem('GYYYY',null,null,'Extrude filament'),
  351. MoveHome : new wmGCommandItem('G28',null,null,'Home all axes'),
  352. MoveHomeX : new wmGCommandItem('G28','X',null,'Home X axis'),
  353. MoveHomeY : new wmGCommandItem('G28','Y',null,'Home Y axis'),
  354. MoveHomeZ : new wmGCommandItem('G28','Z',null,'Home Z axis'),
  355. StepEnable : new wmGCommandItem('M17','{0}','E X Y Z','Enable stepper'),
  356. StepEnableAll : new wmGCommandItem('M17',null,null,'Enable all steppers'),
  357. StepDisable : new wmGCommandItem('M18','{0}','E X Y Z','Disable stepper'),
  358. StepDisableAll: new wmGCommandItem('M18',null,null,'Disable all steppers'),
  359. SdGetList : new wmGCommandItem('M20',null,null,'Get SD card content'),
  360. SdInit : new wmGCommandItem('M21',null,null,'Init SD card'),
  361. SdRelease : new wmGCommandItem('M22',null,null,'Release SD card'),
  362. SdFileSel : new wmGCommandItem('M23','{0}','','Select an SD file'),
  363. SdFilePrint : new wmGCommandItem('M24','{0}','','Start an SD print'),
  364. SdPrintStatus : new wmGCommandItem('M27',null,null,'SD print status'),
  365. SdPrintReport : new wmGCommandItem('M27','S{0}',5,'SD print status report'),
  366. SdFileStart : new wmGCommandItem('M28','{0}','','Start SD write'),
  367. SdFileStop : new wmGCommandItem('M29',null,null,'Stop SD write'),
  368. SdFileDel : new wmGCommandItem('M30','{0}','','Delete an SD file'),
  369. PrintTime : new wmGCommandItem('M31',null,null,'Print time'),
  370. FanOn : new wmGCommandItem('M106','S{0}',128,'Set fan on with speed'),
  371. FanOff : new wmGCommandItem('M107',null,null,'Set fan off'),
  372. GetPosition : new wmGCommandItem('M114',null,null,'Get Current Position'),
  373. FWInfo : new wmGCommandItem('M115',null,null,'Get firmware info',false),
  374. SetTempUnit : new wmGCommandItem('M149','{0}','C','Set temperature units'),
  375. SetTempOff : new wmGCommandItem('M155','S0','','Turn off temperature status'),
  376. SetTempOn : new wmGCommandItem('M155','S{0}',1,'Get temp status (1 sec default)'),
  377. GetSetting : new wmGCommandItem('M503',null,null,'Get settings report')
  378. };
  379. var wmIcons = {
  380. Wifi: new wmFontIcon('wifi'),
  381. Plug: new wmFontIcon('plug'),
  382. Ban: new wmFontIcon('ban'),
  383. Bolt: new wmFontIcon('bolt'),
  384. Info: new wmFontIcon('info'),
  385. InfoCircle: new wmFontIcon('info-circled'),
  386. Triangle: new wmFontIcon('exclamation-triangle'),
  387. CheckSquare: new wmFontIcon('check-square'),
  388. Terminal: new wmFontIcon('terminal'),
  389. Exchange: new wmFontIcon('exchange'),
  390. ChevronUp: new wmFontIcon('chevron-up'),
  391. ChevronDown: new wmFontIcon('chevron-down'),
  392. ChevronLeft: new wmFontIcon('chevron-left'),
  393. ChevronRight: new wmFontIcon('chevron-right'),
  394. LongArrowUp: new wmFontIcon('long-arrow-up'),
  395. LongArrowDown: new wmFontIcon('long-arrow-down'),
  396. LongArrowLeft: new wmFontIcon('long-arrow-left'),
  397. LongArrowRight: new wmFontIcon('long-arrow-right')
  398. };
  399. var wmColors = {
  400. Black : 'rgb(0, 0, 0)',
  401. Blue : 'rgb(54, 162, 235)',
  402. Green : 'rgb(0, 255, 0)',
  403. GreenSuc: 'rgb(92, 184, 92)',
  404. GreenTur: 'rgb(75, 192, 192)',
  405. Grey : 'rgb(201, 203, 207)',
  406. Yellow : 'rgb(255, 205, 86)',
  407. Orange : 'rgb(255, 159, 64)',
  408. Purple : 'rgb(153, 102, 255)',
  409. Red : 'rgb(255, 0, 0)',
  410. RedCoral: 'rgb(255, 99, 132)'
  411. };
  412. // Define default setting onject
  413. jsLog.Verbose("JS Classes initializzation completed");
  414. jsLog.Debug("Default settings loaded: "+wmTools.Stringfy(wmSettings));
  415. wmCookie.Check();