webpack.dev.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /* eslint-disable */
  2. var path = require('path');
  3. const merge = require('webpack-merge');
  4. const common = require('./webpack.common.js');
  5. const bodyParser = require('body-parser')
  6. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  7. const { config } = require('process');
  8. const HtmlWebPackPlugin = require('html-webpack-plugin');
  9. const SpriteLoaderPlugin = require('svg-sprite-loader/plugin');
  10. const { Command } = require('commander');
  11. let cmdLines= { };
  12. var { parseArgsStringToArgv } = require('string-argv');
  13. const data = {
  14. messages: require("../mock/messages.json"),
  15. messagequeue: require("../mock/messages.json"),
  16. message_queue_sequence: [],
  17. message_queue_sequence_post_empty: null,
  18. commands: require("../mock/commands.json"),
  19. scan: require("../mock/scan.json"),
  20. ap: require("../mock/ap.json"),
  21. config: require("../mock/config.json"),
  22. statusdefinition: require("../mock/statusdefinition.json"),
  23. status: require("../mock/status.json"),
  24. messages_ota_fail: require("../mock/messages_ota_fail.json"),
  25. messages_ota: require("../mock/messages_ota.json")
  26. };
  27. const messagingTypes= {
  28. MESSAGING_INFO : 'MESSAGING_INFO',
  29. MESSAGING_WARNING : 'MESSAGING_WARNING',
  30. MESSAGING_ERROR : 'MESSAGING_ERROR'
  31. };
  32. const messagingClass= {
  33. MESSAGING_CLASS_OTA : 'MESSAGING_CLASS_OTA',
  34. MESSAGING_CLASS_SYSTEM : 'MESSAGING_CLASS_SYSTEM',
  35. MESSAGING_CLASS_STATS : 'MESSAGING_CLASS_STATS',
  36. MESSAGING_CLASS_CFGCMD: 'MESSAGING_CLASS_CFGCMD',
  37. MESSAGING_CLASS_BT: 'MESSAGING_CLASS_BT'
  38. } ;
  39. function requeueMessages(){
  40. data.messagequeue = [];
  41. data.messagequeue.push(...data.messages);
  42. console.log(`Re-queued ${data.messages.length} messages. Total queue length is: ${data.messagequeue.length}`);
  43. }
  44. function sendMessaging(cmdname,msgtype,msgClass,msg){
  45. let message_txt=`${cmdname}\n${msg}`;
  46. var d = new Date();
  47. var n = d.getMilliseconds();
  48. data.messagequeue.push({
  49. message: message_txt,
  50. type: msgtype,
  51. class: msgClass,
  52. sent_time: n,
  53. current_time: n});
  54. console.log(`Queued message ~${data.messagequeue.length} type ${msgtype}, class ${msgClass}: ${message_txt}`);
  55. }
  56. Array.prototype.filter = function(fun /*, thisp*/) {
  57. var len = this.length >>> 0;
  58. if (typeof fun != "function")
  59. throw new TypeError();
  60. var res = [];
  61. var thisp = arguments[1];
  62. for (var i = 0; i < len; i++) {
  63. if (i in this) {
  64. var val = this[i];
  65. if (fun.call(thisp, val, i, this))
  66. res.push(val);
  67. }
  68. }
  69. return res;
  70. };
  71. for(const cmdIdx in data.commands.commands){
  72. const cmd = data.commands.commands[cmdIdx];
  73. //console.log(`Creating command structure for ${cmd.name}`);
  74. cmdLines[cmd.name] = {
  75. cmd: new Command(),
  76. };
  77. cmdLines[cmd.name].cmd
  78. .storeOptionsAsProperties(true)
  79. .name(cmd.name)
  80. .exitOverride();
  81. for(const argIdx in cmd.argtable){
  82. const arg=cmd.argtable[argIdx];
  83. const optstr=((arg.shortopts?'-'+arg.shortopts:'')+
  84. (arg.shortopts && arg.longopts?', ':'')+
  85. (arg.longopts?'--'+arg.longopts:'') +
  86. (arg.hasvalue?`${(arg.shortopts || arg.longopts?' ':'')}<${arg.datatype.replace(/[<>]/gm,'')}>`:''));
  87. //console.log(` Option: ${optstr}, Glossary: ${arg.glossary}`);
  88. if(arg.mincount>0){
  89. cmdLines[cmd.name].cmd.requiredOption( optstr,arg.glossary);
  90. }
  91. else {
  92. cmdLines[cmd.name].cmd.option( optstr,arg.glossary);
  93. }
  94. }
  95. }
  96. const connectReturnCode = {
  97. UPDATE_CONNECTION_OK : 0,
  98. UPDATE_FAILED_ATTEMPT : 1,
  99. UPDATE_USER_DISCONNECT : 2,
  100. UPDATE_LOST_CONNECTION : 3,
  101. UPDATE_FAILED_ATTEMPT_AND_RESTORE : 4
  102. }
  103. module.exports = merge(common, {
  104. mode: 'development',
  105. devtool: 'inline-source-map',
  106. entry: {
  107. test: './src/test.ts'
  108. },
  109. devServer: {
  110. contentBase: path.join(__dirname, 'dist'),
  111. publicPath: '/',
  112. port: 9100,
  113. host: '127.0.0.1',//your ip address
  114. disableHostCheck: true,
  115. headers: {'Access-Control-Allow-Origin': '*',
  116. 'Accept-Encoding': 'identity'},
  117. overlay: true,
  118. before: function(app) {
  119. app.use(bodyParser.json()) // for parsing application/json
  120. app.use(bodyParser.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded
  121. app.get('/ap.json', function(req, res) { res.json( data.ap ); });
  122. app.get('/scan.json', function(req, res) { res.json( data.scan ); });
  123. app.get('/config.json', function(req, res) { res.json( data.config ); });
  124. app.get('/status.json', function(req, res) { res.json( data.status ); });
  125. app.get('/plugins/SqueezeESP32/firmware/-99', function(req, res) {
  126. let has_proxy= data.status.mock_plugin_has_proxy ?? 'n';
  127. const statusCode='xy'.includes((has_proxy).toLowerCase())?200:500;
  128. console.log(`Checking if plugin has proxy enabled with option mock_plugin_has_proxy = ${data.status.mock_plugin_has_proxy}. Returning status ${statusCode} `);
  129. res.status(statusCode ).json();
  130. });
  131. app.get('/messages.json', function(req, res) {
  132. if(data.message_queue_sequence.length>0){
  133. data.messagequeue.push(data.message_queue_sequence.shift());
  134. }
  135. else if (data.message_queue_sequence_post_empty){
  136. data.message_queue_sequence_post_empty();
  137. data.message_queue_sequence_post_empty = null;
  138. }
  139. res.json( data.messagequeue ) ;
  140. data.messagequeue=[];
  141. });
  142. app.get('/statusdefinition.json', function(req, res) { res.json( data.statusdefinition ); });
  143. app.get('/commands.json', function(req, res) { res.json( data.commands ); });
  144. app.post('/commands.json', function(req, res) {
  145. console.log(req.body.command);
  146. try {
  147. const cmdName=req.body.command.split(" ")[0];
  148. const args=parseArgsStringToArgv(req.body.command,'node ');
  149. let cmd=cmdLines[cmdName].cmd;
  150. if(cmd){
  151. for (const property in cmd.opts()) {
  152. delete cmd[property];
  153. }
  154. cmd.parse(args);
  155. const msg=`Received Options: ${JSON.stringify(cmd.opts())}\n`;
  156. console.log('Options: ', cmd.opts());
  157. console.log('Remaining arguments: ', cmd.args);
  158. sendMessaging(cmdName,messagingTypes.MESSAGING_INFO,messagingClass.MESSAGING_CLASS_CFGCMD,msg);
  159. }
  160. } catch (error) {
  161. console.error(error);
  162. }
  163. res.json( { 'Result' : 'Success' } );
  164. });
  165. app.post('/config.json', function(req, res) {
  166. var fwurl='';
  167. console.log(`Processing config.json with request body: ${req.body}`);
  168. console.log(data.config);
  169. for (const property in req.body.config) {
  170. console.log(`${property}: ${req.body.config[property].value}`);
  171. if(property=='fwurl'){
  172. fwurl=req.body.config[property].value;
  173. }
  174. else {
  175. if(data.config[property]=== undefined){
  176. console.log(`Added config value ${property} [${req.body.config[property].value}]`);
  177. data.config[property] = {value: req.body.config[property].value};
  178. }
  179. else if (data.config[property].value!=req.body.config[property].value){
  180. console.log(`Updated config value ${property}\nFrom: ${data.config[property].value}\nTo: ${req.body.config[property].value}]`);
  181. data.config[property].value=req.body.config[property].value;
  182. }
  183. }
  184. }
  185. res.json( {} );
  186. if(fwurl!=='' ){
  187. if(data.status.recovery!=1) {
  188. // we're not yet in recovery. Simulate reboot to recovery
  189. data.status.recovery=1;
  190. requeueMessages();
  191. }
  192. if(fwurl.toLowerCase().includes('fail')){
  193. console.log(`queuing ${data.messages_ota_fail.length} ota messages `);
  194. data.message_queue_sequence.push(...data.messages_ota_fail);
  195. }
  196. else {
  197. console.log(`queuing ${data.messages_ota.length} ota messages `);
  198. data.message_queue_sequence.push(...data.messages_ota);
  199. data.message_queue_sequence_post_empty = function(){
  200. data.status.recovery=0;
  201. requeueMessages();
  202. }
  203. }
  204. }
  205. });
  206. app.post('/status.json', function(req, res) {
  207. for (const property in req.body.status) {
  208. if(data.status[property]=== undefined){
  209. console.log(`Added status value ${property} [${req.body.status[property]}]`);
  210. data.status[property] = {value: req.body.status[property]};
  211. }
  212. else if (data.status[property]!==req.body.status[property]){
  213. console.log(`Updated status value ${property}\nFrom: ${data.status[property]}\nTo: ${req.body.status[property]}`);
  214. data.status[property]=req.body.status[property];
  215. }
  216. }
  217. res.json( {} );
  218. });
  219. app.post('/connect.json', function(req, res) {
  220. setTimeout(function(r){
  221. if(r.body.ssid.search('fail')>=0){
  222. if(data.status.ssid){
  223. // in this case, the same ssid will be reused - the ESP32 would restore its previous state on failure
  224. data.status.urc=connectReturnCode.UPDATE_FAILED_ATTEMPT_AND_RESTORE;
  225. }
  226. else {
  227. data.status.urc=connectReturnCode.UPDATE_FAILED_ATTEMPT;
  228. }
  229. }
  230. else {
  231. data.status.ssid=r.body.ssid;
  232. data.status.urc=connectReturnCode.UPDATE_CONNECTION_OK;
  233. }
  234. }, 1000, req);
  235. res.json( {} );
  236. });
  237. app.post('/reboot_ota.json', function(req, res) {
  238. data.status.recovery=0;
  239. requeueMessages();
  240. res.json( {} );
  241. });
  242. app.post('/reboot.json', function(req, res) {
  243. res.json( {} );
  244. requeueMessages();
  245. });
  246. app.post('/recovery.json', function(req, res) {
  247. data.status.recovery=1;
  248. requeueMessages();
  249. res.json( { } );
  250. });
  251. app.post('/flash.json', function(req, res) {
  252. if(data.status.recovery>0){
  253. res.json({});
  254. }
  255. else {
  256. res.status(404).end();
  257. }
  258. });
  259. app.delete('/connect.json', function(req, res) {
  260. data.status.ssid='';
  261. res.json( {} ); });
  262. app.get('/reboot', function(req, res) { res.json( {} ); });
  263. },
  264. },
  265. plugins: [
  266. new MiniCssExtractPlugin({
  267. filename: 'css/[name].css',
  268. chunkFilename: 'css/[id].css' ,
  269. }),
  270. new HtmlWebPackPlugin({
  271. title: 'SqueezeESP32-test',
  272. template: './src/test.ejs',
  273. filename: 'test',
  274. minify: false,
  275. excludeChunks: ['index'],
  276. }),
  277. new SpriteLoaderPlugin({plainSprite: true})
  278. ],
  279. });