39 changed files with 18346 additions and 10761 deletions
@ -1,3 +1,4 @@
@@ -1,3 +1,4 @@
|
||||
node_modules |
||||
bin |
||||
web/dist |
||||
.pio |
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
module.exports = { |
||||
presets: [ |
||||
'@babel/preset-env' |
||||
] |
||||
} |
@ -1,108 +0,0 @@
@@ -1,108 +0,0 @@
|
||||
#ifndef __embed_css |
||||
#define __embed_css |
||||
|
||||
#include <pgmspace.h> |
||||
|
||||
const uint8_t EmbeddedBundleCSS[] PROGMEM = { |
||||
0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0xad,0x59,0xd9,0x8e,0xa3,0x3a,0x1a,0x7e,0x95,0x48, |
||||
0xa5,0x96,0xba,0x46,0x80,0x08,0x49,0xa8,0x2a,0xd0,0x19,0xcd,0x68,0xde,0x60,0x2e,0xe6,0xa6,0x55,0x17, |
||||
0x06,0x4c,0xb0,0x8a,0x60,0x64,0x9c,0x5a,0x1a,0xf1,0xee,0xf3,0x7b,0x4b,0x6c,0x30,0xe9,0xf4,0x39,0x47, |
||||
0xa8,0x16,0x6c,0xff,0xab,0xff,0xe5,0xb3,0x69,0xf8,0xa9,0x1d,0xe9,0x3b,0x66,0x43,0xc9,0x68,0xdb,0x86, |
||||
0x05,0x6e,0xd0,0x3b,0xa1,0x2c,0xfc,0xcc,0x4a,0xda,0x71,0x44,0xba,0xbc,0xa0,0x9f,0xe1,0x40,0x7e,0x92, |
||||
0xee,0x98,0x15,0x94,0x55,0x98,0x85,0x30,0x92,0xd7,0x30,0x2b,0x86,0x71,0x96,0x26,0xd1,0xe1,0xdb,0xf4, |
||||
0x8f,0x20,0x43,0x35,0xc7,0x2c,0xc8,0x0a,0x5c,0x53,0x86,0x47,0x8b,0x8c,0x74,0x0d,0x66,0x84,0x4f,0x05, |
||||
0xad,0xbe,0x7e,0x25,0x0c,0x95,0x6f,0x47,0x46,0xcf,0x5d,0x15,0x96,0xb4,0xa5,0x2c,0x7b,0xd8,0xee,0xc5, |
||||
0x93,0xeb,0xb7,0xba,0xae,0x95,0xe8,0x1a,0x9d,0x48,0xfb,0x95,0xfd,0x0f,0xb3,0x0a,0x75,0x28,0xf8,0x37, |
||||
0x23,0xa8,0x0d,0x06,0xd4,0x0d,0xe1,0x00,0xb2,0x6a,0x4b,0xbf,0x6d,0xb4,0xc3,0x27,0xf5,0xfe,0x81,0xc9, |
||||
0xb1,0xe1,0xd9,0x2e,0x8e,0xf3,0x16,0x73,0xd0,0x36,0x1c,0x7a,0x54,0x0a,0x15,0xa3,0x78,0x0b,0x8b,0x5a, |
||||
0xd2,0xe1,0xb0,0x51,0x8b,0x80,0x2c,0xef,0x51,0x55,0xc1,0x2c,0x18,0xcc,0x39,0x3d,0x65,0x3b,0x86,0x4f, |
||||
0xd3,0xbf,0x4e,0xb8,0x22,0x68,0x03,0x26,0x60,0xdc,0x6d,0x50,0x57,0x6d,0xbe,0x9f,0x48,0x17,0x7e,0x90, |
||||
0x8a,0x37,0xd9,0x53,0xfa,0xdc,0x7f,0x3e,0x8e,0xd2,0x50,0x43,0xcc,0x69,0xaf,0x28,0x27,0x34,0x72,0xfc, |
||||
0xc9,0xc3,0x0a,0x97,0x94,0x21,0x4e,0x68,0x97,0x75,0xb4,0xc3,0xd3,0x8f,0xf7,0xb0,0x6c,0x29,0x7a,0x7b, |
||||
0x1d,0x2b,0x32,0xf4,0x2d,0xfa,0x52,0xc3,0x0f,0xda,0x27,0x98,0x8d,0x57,0xaf,0x64,0x0f,0x49,0x2c,0x9e, |
||||
0xfc,0x84,0xd8,0x11,0xc4,0x0a,0xe6,0x09,0x30,0x37,0xaa,0x66,0x5b,0xf1,0x22,0x7d,0xdf,0xa0,0x8a,0x7e, |
||||
0x64,0xf1,0x26,0xde,0x1c,0xe2,0xfe,0x73,0xf3,0x50,0x97,0x75,0x5a,0xd6,0xb9,0xda,0xc3,0x6c,0xa0,0x2d, |
||||
0xa9,0x36,0x5b,0x31,0x11,0xc7,0xf1,0x5d,0x56,0x59,0x0a,0x59,0xe3,0x46,0x93,0x16,0xd7,0x3c,0x43,0x67, |
||||
0x4e,0xcd,0x00,0x93,0x6e,0x14,0x23,0xd3,0x14,0x35,0x18,0x81,0xd4,0xb1,0xa7,0x03,0x91,0x86,0x33,0xdc, |
||||
0x82,0x07,0xde,0xb1,0x99,0xd9,0x90,0xd3,0x71,0xac,0xc1,0x0b,0x3c,0x13,0x8c,0x5c,0x1e,0xdb,0x35,0xbf, |
||||
0xa3,0xcf,0x8b,0x86,0x4f,0x42,0x43,0xc3,0x2c,0xfa,0x20,0x35,0x19,0x38,0xe2,0xe7,0x61,0x2c,0x5b,0x8c, |
||||
0x18,0x44,0x2e,0x6f,0x6c,0x9f,0xa9,0x0d,0xb9,0xc7,0x6a,0x1f,0xcf,0x8b,0x19,0xa8,0x00,0x3f,0x9e,0x39, |
||||
0xce,0x95,0xa2,0x71,0x2e,0x78,0xc7,0x17,0x7b,0x6d,0xa2,0x4d,0x44,0xba,0x8a,0x94,0x88,0x53,0x76,0xd9, |
||||
0x67,0xd2,0xc9,0x88,0x2b,0x5a,0x5a,0xbe,0xe5,0x4a,0xaa,0xdc,0x3f,0x13,0x82,0x6a,0x2f,0x65,0xce,0x31, |
||||
0x54,0x91,0xf3,0x90,0x1d,0xe2,0x6f,0xae,0x6f,0xa2,0x83,0xb0,0xe4,0xb6,0xbc,0x1f,0x15,0xe2,0x28,0x54, |
||||
0xc3,0x7f,0xc0,0x26,0x76,0xb8,0xe4,0xb8,0x7a,0x1d,0x97,0xc9,0xb6,0x7b,0x49,0x7f,0x87,0x17,0xd8,0x61, |
||||
0xb3,0x9b,0x47,0xd6,0x91,0xe1,0xaf,0x3f,0xa1,0x1a,0x84,0xb1,0x4f,0xb7,0xfa,0x65,0xf7,0x3b,0xcc,0x30, |
||||
0x63,0x94,0xf9,0xf8,0x94,0x10,0xee,0x51,0x71,0x86,0x8c,0xee,0x82,0xa8,0x6c,0x70,0xf9,0xb6,0x89,0x44, |
||||
0x64,0x43,0x49,0x0a,0xa2,0x8e,0x72,0xe0,0x5c,0xca,0xec,0x0c,0xa2,0x1e,0x75,0xb8,0xdd,0xa8,0x3f,0xa1, |
||||
0x48,0xea,0xd9,0x90,0xd2,0x26,0x88,0xc4,0xe6,0x50,0x8b,0xcb,0x07,0x62,0x1d,0x58,0x11,0x68,0x29,0xcd, |
||||
0x2e,0x20,0x5d,0x7f,0xe6,0x3f,0xf8,0x57,0x8f,0xff,0x18,0xce,0xc5,0x89,0xf0,0xd7,0x60,0xc0,0x2d,0x18, |
||||
0x6b,0xbc,0x26,0xfc,0xa5,0x3c,0xf7,0xb0,0xdd,0x6e,0x67,0xbb,0xbe,0x83,0x34,0xb3,0x72,0x9a,0x74,0x03, |
||||
0xe6,0x90,0xd7,0x82,0x86,0x1d,0x0b,0xf4,0x3d,0x39,0x1c,0x02,0xf3,0x13,0x6d,0x1f,0x03,0xb3,0x20,0x14, |
||||
0x2b,0x76,0x66,0x55,0x1c,0x88,0x27,0xda,0x5d,0xe7,0xe3,0x55,0x26,0xf1,0xf3,0x63,0xa0,0xe6,0x92,0x19, |
||||
0xf9,0xf6,0xf0,0x68,0xdc,0x17,0xa1,0x52,0xe4,0x70,0xa0,0x5f,0x33,0xfd,0xea,0x4e,0xba,0x73,0xd2,0x0f, |
||||
0x7a,0xca,0x75,0x87,0xe5,0xa1,0xee,0x7c,0x2a,0x30,0x73,0x86,0x7a,0x34,0x0c,0x1f,0xe0,0x93,0x57,0x8f, |
||||
0x27,0x1d,0xde,0x6a,0x46,0xd4,0xd9,0xd7,0x40,0xfc,0x46,0x0c,0xa3,0xdb,0x3e,0xd6,0x61,0x01,0x55,0x50, |
||||
0x0e,0x9b,0x39,0xaf,0xb7,0xe7,0xce,0x48,0x0e,0xc6,0x4d,0x5e,0x17,0x4e,0x3a,0x00,0xa4,0x66,0xe3,0x3d, |
||||
0x7d,0x6b,0x52,0x4b,0xa1,0x53,0x15,0x6f,0x84,0x87,0xa8,0xef,0xa1,0x7a,0xa1,0xae,0xc4,0xb2,0x27,0xe4, |
||||
0xe1,0x89,0xfe,0x5c,0x0c,0xce,0xde,0x2f,0xc1,0x6d,0x0b,0x77,0x1c,0xe6,0xaf,0x3f,0xa6,0x83,0x80,0x3d, |
||||
0x60,0xa6,0x69,0xb8,0x55,0x55,0xe5,0x76,0xfb,0xd9,0xc7,0xe2,0xc9,0xcb,0x33,0x1b,0x60,0xba,0xa7,0xa4, |
||||
0x83,0x36,0xea,0x34,0x4e,0x59,0x5a,0x4d,0x84,0xd4,0xb4,0x3c,0x0f,0x97,0x00,0x71,0xdf,0x1a,0x01,0x05, |
||||
0x02,0x67,0xa1,0xb3,0xce,0x59,0xb6,0xb4,0x42,0x93,0x78,0xe2,0x61,0x75,0x42,0xb2,0x1a,0x57,0x2c,0x3b, |
||||
0xc4,0xe2,0xc9,0xe9,0x99,0x0b,0x6b,0xb2,0xf8,0xaf,0x46,0xb9,0xab,0xec,0xea,0x8c,0xa6,0x31,0x5a,0x95, |
||||
0x65,0xe9,0x68,0x95,0x3c,0x8b,0xc7,0xe8,0x12,0xf6,0x8c,0x40,0xf9,0xff,0xf2,0x6d,0xaa,0x43,0x95,0xa4, |
||||
0x07,0xb4,0x9d,0x53,0xb9,0xbb,0x61,0x46,0x33,0xff,0xe8,0xdf,0xee,0x76,0x47,0xbf,0xf4,0x29,0x29,0xd2, |
||||
0x09,0x69,0xa1,0x7e,0x5c,0x14,0x75,0x80,0x0e,0x8f,0x72,0xe0,0x56,0x17,0x8f,0x38,0x74,0xe1,0x7f,0x1a, |
||||
0x4e,0x36,0x1a,0x11,0xe5,0x6f,0x56,0x49,0x63,0x77,0x79,0x56,0x13,0x36,0xf0,0xb0,0x6c,0x48,0x5b,0x39, |
||||
0xa4,0xf1,0xb2,0x02,0xcb,0x6a,0x09,0x7f,0x67,0x1c,0x5a,0x74,0x61,0x30,0x13,0x25,0x2b,0xaf,0x24,0x9c, |
||||
0x0b,0x15,0x8e,0x5a,0x62,0xa1,0xfc,0x67,0x08,0xad,0x0c,0x7f,0x66,0xb0,0x71,0x02,0x24,0x4b,0xbb,0x65, |
||||
0x54,0x88,0x46,0x6a,0x21,0xda,0xe7,0x9e,0xe7,0xd2,0x63,0xa8,0x25,0xc7,0x2e,0x2b,0xb1,0xcc,0xc1,0x19, |
||||
0x22,0x9c,0x9c,0x5e,0xf6,0x9f,0x0b,0x74,0xbb,0x88,0xad,0xc9,0x27,0xae,0xf2,0x0b,0x80,0x34,0xc2,0xd3, |
||||
0x34,0xbd,0x0f,0x17,0xf9,0xd9,0xab,0x35,0x07,0x59,0x42,0xa4,0x27,0x01,0xb1,0x4c,0xae,0x2e,0x6e,0x24, |
||||
0xbc,0x3c,0xa1,0xe2,0x79,0x8e,0x58,0xb7,0xb1,0x06,0xa6,0x36,0xee,0x9f,0xd5,0x1c,0x53,0xaf,0xa2,0x03, |
||||
0x68,0xaf,0x8d,0xd7,0x40,0x5d,0x21,0xe2,0x05,0xd6,0xfc,0x6d,0xb3,0x46,0x15,0x46,0x4b,0x13,0x36,0xd1, |
||||
0x09,0x0f,0x03,0x3a,0xe2,0xf1,0xa3,0x21,0x1c,0xcb,0x63,0x04,0xce,0x7a,0x86,0xdd,0x65,0x91,0x04,0x21, |
||||
0x8e,0xbd,0x2f,0x4f,0x3b,0xb4,0x83,0x7c,0x96,0xc0,0x43,0x23,0x07,0x7f,0x3d,0x9e,0x99,0x7b,0x1e,0xc4, |
||||
0x71,0x45,0x62,0x06,0x55,0xf6,0x6d,0xc9,0x1d,0xfd,0x60,0xa8,0xb7,0x43,0xc0,0xe3,0x15,0x31,0x34,0x2d, |
||||
0x10,0x8f,0x8b,0x5d,0x46,0x4f,0xad,0xbf,0x85,0x56,0x53,0xd8,0x66,0x83,0x56,0xc5,0xff,0x1e,0x80,0xaf, |
||||
0x05,0xb6,0xa8,0xc0,0x57,0x71,0xf2,0xcd,0x6f,0xb7,0x9d,0x86,0xd2,0x0a,0xc8,0x05,0x0e,0x0e,0x6d,0x75, |
||||
0xb8,0x83,0x75,0x9a,0xa9,0xfa,0x8d,0xab,0xb9,0x35,0x8b,0x71,0xc7,0xaa,0x34,0x16,0x8f,0x61,0x01,0x2a, |
||||
0xa0,0xa2,0xc5,0x95,0x21,0x35,0xef,0xa3,0x76,0x3f,0x6c,0x27,0xc8,0x6d,0xe9,0x07,0xae,0xe6,0x24,0xae, |
||||
0x4d,0xf3,0x61,0x2b,0x75,0xa7,0x05,0x40,0x74,0xdf,0x05,0x84,0x95,0xc7,0xbc,0x39,0xd4,0x9f,0x13,0x9a, |
||||
0x85,0x57,0xc8,0x92,0x2f,0x8f,0x22,0x62,0xf7,0xf7,0x26,0xfb,0xc4,0x3f,0x6a,0xab,0xac,0x9d,0x4a,0x45, |
||||
0x11,0xf3,0x7b,0xea,0xa2,0x8a,0xe5,0x30,0xd9,0x92,0xec,0xfc,0xdc,0xce,0x50,0x90,0x40,0x84,0x6e,0x58, |
||||
0x19,0x36,0x7e,0xed,0x0e,0x37,0xb5,0x93,0x25,0xd6,0xbf,0xbf,0xae,0xa3,0xf4,0x49,0x63,0x89,0xbc,0x9e, |
||||
0x1f,0x4d,0xf5,0x56,0xcc,0x45,0x45,0x49,0x14,0x7a,0xcb,0x39,0x00,0xa5,0xa1,0xa6,0xec,0x94,0x31,0x0a, |
||||
0x07,0x05,0xfc,0x3d,0xdc,0x1f,0x2a,0x7c,0x7c,0xb4,0x2d,0x94,0xb0,0x39,0x76,0x81,0x9e,0x83,0xf3,0x2c, |
||||
0xbb,0x05,0xab,0xd0,0x84,0x99,0x95,0x7f,0x5b,0xc8,0xb5,0x3f,0x01,0x69,0xe7,0xc0,0xd5,0x83,0xbc,0xae, |
||||
0x05,0xd1,0xa9,0x80,0x3a,0x21,0x63,0x88,0x1a,0x73,0xb2,0xb8,0x49,0x7c,0xd7,0x2d,0x8a,0x2d,0xc1,0x36, |
||||
0x07,0x9c,0x78,0xc4,0xaf,0x8e,0xbd,0x6c,0x51,0x6f,0xe4,0xb1,0xbd,0xd9,0x8e,0xd7,0xc6,0x95,0x5c,0x17, |
||||
0x41,0x27,0x6e,0x12,0x1d,0xc8,0x03,0x69,0x21,0xc7,0x9d,0x2b,0x9b,0xd9,0xca,0x9d,0xdd,0x08,0x97,0xf0, |
||||
0x68,0x49,0x7a,0x55,0x5c,0x2a,0xb1,0x1f,0xed,0x15,0x7b,0x76,0xb1,0xc6,0x24,0xed,0xab,0x27,0xdf,0xf3, |
||||
0x35,0x99,0xa9,0x78,0x26,0xb7,0x84,0x39,0xb5,0xeb,0x66,0x01,0x96,0x74,0xa1,0x2a,0x79,0xa3,0x73,0x96, |
||||
0x4f,0xee,0xbd,0x5f,0x8a,0x1a,0xca,0xc8,0x4f,0xd1,0x73,0x5b,0x0b,0x19,0x4d,0xd6,0xf0,0x66,0xbd,0xc0, |
||||
0x3a,0xcb,0x3c,0x21,0xba,0x32,0x7d,0x0d,0xd7,0x95,0x05,0x2a,0x74,0xed,0xc9,0x4b,0x18,0x7b,0xeb,0xbc, |
||||
0xba,0xed,0x91,0x96,0xeb,0xe0,0x95,0x15,0xef,0x4a,0xaf,0x2e,0x14,0x6d,0x03,0x61,0x16,0x9a,0xe1,0xcc, |
||||
0xe7,0x2e,0x2e,0xb2,0xf6,0x6c,0x16,0x8d,0xfa,0xa6,0x04,0xa4,0x8a,0xc8,0x18,0x67,0x30,0x72,0x09,0xa8, |
||||
0xa6,0x08,0xf0,0x2b,0xed,0x45,0xf9,0x1a,0x1c,0x6c,0x78,0xb0,0x0e,0x38,0xce,0xfd,0xd2,0x4d,0x4c,0x26, |
||||
0xb3,0x21,0x1a,0xa0,0x62,0x01,0xb4,0x1b,0x17,0x60,0x4d,0x4d,0x5c,0x6f,0xd8,0x56,0x28,0x57,0x4f,0x86, |
||||
0xd7,0xf4,0x37,0x75,0x54,0xda,0x3b,0x83,0xb1,0x70,0x60,0x95,0x83,0xcb,0xca,0x60,0x1d,0x7b,0x94,0xa4, |
||||
0x2c,0x33,0xa2,0xd4,0x7b,0xc8,0x1b,0x08,0x90,0x55,0xf9,0x7e,0x7d,0x12,0xeb,0x36,0x2b,0xf1,0xdf,0x66, |
||||
0xd9,0xba,0xe8,0x2b,0x4a,0x17,0xf9,0x58,0x0a,0x89,0xd3,0xaf,0x2c,0x3d,0x5a,0x99,0xbf,0x5f,0x48,0xc4, |
||||
0x70,0xb5,0x62,0xb9,0xd3,0x12,0xf1,0x2e,0xdd,0xa5,0x33,0xa2,0xb9,0x76,0x37,0x08,0x8e,0x22,0xb9,0xef, |
||||
0x90,0xb3,0x4b,0x8a,0xa7,0x5d,0xb2,0x20,0xbb,0x25,0x69,0x46,0x52,0xb4,0x67,0x7c,0x87,0xa0,0x7d,0xba, |
||||
0x4f,0xcb,0x72,0x4e,0x75,0x4b,0x8e,0xa1,0xd0,0x77,0x5d,0x1e,0x90,0xfb,0x4b,0x84,0xbe,0x88,0xf1,0x8e, |
||||
0x8a,0x1b,0x3c,0xbb,0xd6,0x7b,0xb2,0x52,0x26,0x9c,0x53,0xf6,0xe4,0x65,0xdc,0xe8,0x3b,0x02,0x98,0x2b, |
||||
0x8d,0xc9,0x77,0x6f,0x37,0x2e,0x8f,0x78,0xfa,0x98,0x97,0x5f,0x3e,0x74,0x08,0x5e,0x06,0x45,0xb8,0xf6, |
||||
0xdc,0xec,0xae,0x5e,0x79,0xba,0x26,0x5b,0x9d,0x48,0xd8,0xec,0x5b,0x28,0x6f,0x0b,0x44,0x71,0xb1,0x6a, |
||||
0xe4,0xca,0x4a,0x0d,0x41,0x7d,0x73,0xc6,0x91,0x1e,0x85,0xe4,0x07,0x8a,0xf9,0x71,0xf5,0x72,0x60,0x75, |
||||
0x6c,0xdb,0xc5,0xe2,0xb9,0xd8,0xae,0xaa,0x95,0xe4,0xa2,0xef,0x34,0xe6,0x4e,0xb5,0x69,0x8b,0x3d,0x3a, |
||||
0x3c,0x3b,0x7e,0xd1,0x7d,0xef,0xc6,0x99,0x42,0x7e,0x31,0x88,0x6a,0x60,0x16,0xca,0x1d,0x0f,0xcd,0xfd, |
||||
0x8b,0x1c,0x82,0x6d,0x7f,0xc7,0x7a,0x68,0x94,0x60,0x4e,0x01,0x4c,0x2a,0x3e,0xe4,0xf0,0xaf,0x4d,0x74, |
||||
0x18,0x6c,0x62,0x87,0x8a,0xd3,0x51,0x2f,0x13,0x11,0x21,0x03,0xdb,0x89,0x23,0x39,0xb2,0x89,0x06,0x68, |
||||
0x5a,0xdc,0x73,0x3c,0xbf,0xa1,0xf3,0xfe,0xe5,0x9b,0x4b,0xbe,0x59,0x2b,0xe8,0xaa,0xd3,0xef,0x85,0x13, |
||||
0xdd,0xf5,0xef,0x08,0x72,0xee,0x17,0x5f,0x16,0x54,0x0f,0xcb,0xdd,0x93,0x85,0x64,0x82,0xbb,0xea,0x5e, |
||||
0x8d,0x57,0xfa,0xee,0x95,0xd1,0xaa,0xee,0x0a,0xb3,0x5b,0xaa,0xcb,0xc5,0x6b,0x8a,0xeb,0x7b,0x94,0x5b, |
||||
0x7a,0x2f,0x3b,0x3c,0x94,0xd2,0x01,0xf3,0xff,0x62,0x34,0xcc,0xee,0x72,0x12,0x10,0xfb,0x7f,0x44,0x42, |
||||
0x49,0x9a,0xad,0x1c,0x00,0x00}; |
||||
|
||||
#endif |
@ -1,615 +0,0 @@
@@ -1,615 +0,0 @@
|
||||
function startApp() |
||||
{ |
||||
// Source: https://github.com/axios/axios/issues/164
|
||||
axios.interceptors.response.use(undefined, function axiosRetryInterceptor(err) { |
||||
var config = err.config; |
||||
// If config does not exist or the retry option is not set, reject
|
||||
if(!config || !config.retry) return Promise.reject(err); |
||||
|
||||
// Set the variable for keeping track of the retry count
|
||||
config.__retryCount = config.__retryCount || 0; |
||||
|
||||
// Check if we've maxed out the total number of retries
|
||||
if(config.__retryCount >= config.retry) { |
||||
// Reject with the error
|
||||
return Promise.reject(err); |
||||
} |
||||
|
||||
// Increase the retry count
|
||||
config.__retryCount += 1; |
||||
|
||||
// Create new promise to handle exponential backoff
|
||||
var backoff = new Promise(function(resolve) { |
||||
setTimeout(function() { |
||||
resolve(); |
||||
}, config.retryDelay || 1); |
||||
}); |
||||
|
||||
// Return the promise in which recalls axios to retry the request
|
||||
return backoff.then(function() { |
||||
return axios(config); |
||||
}); |
||||
}); |
||||
|
||||
Vue.component('check', { |
||||
template: '<div class="check" :class="{ checked: value, disabled: disabled }" @keydown="handleKeyDown" @click="handleClick" tabindex="0"><div class="control"><div class="inner"></div></div><div class="label">{{ title }}</div></div>', |
||||
props: { |
||||
title: String, |
||||
value: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
disabled: { |
||||
type: Boolean, |
||||
default: false |
||||
} |
||||
}, |
||||
|
||||
methods: { |
||||
handleClick: function() |
||||
{ |
||||
if (this.disabled) return; |
||||
this.value = !this.value; |
||||
this.$emit('input', this.value); |
||||
}, |
||||
|
||||
handleKeyDown: function(event) |
||||
{ |
||||
if (event.keyCode == 32) |
||||
{ |
||||
this.handleClick(); |
||||
event.preventDefault(); |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
|
||||
|
||||
Vue.component('radio', { |
||||
template: '<div class="radio" :class="{ checked: value == id, disabled: disabled }" @keydown="handleKeyDown" @click="handleClick" tabindex="0"><div class="control"><div class="inner"></div></div><div class="label">{{ title }}</div></div>', |
||||
props: { |
||||
title: String, |
||||
value: null, |
||||
id: null, |
||||
disabled: { |
||||
type: Boolean, |
||||
default: false |
||||
} |
||||
}, |
||||
|
||||
methods: { |
||||
handleClick: function() |
||||
{ |
||||
if (this.disabled) return; |
||||
this.value = this.id; |
||||
this.$emit('input', this.value); |
||||
}, |
||||
|
||||
handleKeyDown: function(event) |
||||
{ |
||||
if (event.keyCode == 32) |
||||
{ |
||||
this.handleClick(); |
||||
event.preventDefault(); |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
|
||||
|
||||
Vue.component('range', { |
||||
template: '<div>' + |
||||
'<div class="start">' + |
||||
'<span class="value">{{ value.start }}</span>' + |
||||
'<div class="slidercontainer">' + |
||||
'<input type="range" min="0" max="4094" class="slider" v-model.number="value.start">' + |
||||
'</div>' + |
||||
'</div>' + |
||||
|
||||
'<div class="end">' + |
||||
'<span class="value">{{ value.end }}</span>' + |
||||
'<div class="slidercontainer">' + |
||||
'<input type="range" min="1" max="4095" class="slider" v-model.number="value.end">' + |
||||
'</div>' + |
||||
'</div>' + |
||||
'</div>', |
||||
props: ['value'], |
||||
|
||||
mounted: function() |
||||
{ |
||||
this.oldValue = { start: this.value.start, end: this.value.end }; |
||||
}, |
||||
|
||||
watch: { |
||||
value: { |
||||
handler: function(newValue) |
||||
{ |
||||
if (newValue.start != this.oldValue.start) |
||||
{ |
||||
if (newValue.start > newValue.end) |
||||
{ |
||||
newValue.end = newValue.start + 1; |
||||
this.$emit('input', newValue); |
||||
} |
||||
} |
||||
else if (newValue.end != this.oldValue.end) |
||||
{ |
||||
if (newValue.end < newValue.start) |
||||
{ |
||||
newValue.start = newValue.end - 1; |
||||
this.$emit('input', newValue); |
||||
} |
||||
} |
||||
|
||||
this.oldValue.start = newValue.start; |
||||
this.oldValue.end = newValue.end; |
||||
}, |
||||
deep: true |
||||
} |
||||
} |
||||
}); |
||||
|
||||
var i18n = new VueI18n({ |
||||
locale: navigator.language.split('-')[0], |
||||
fallbackLocale: 'en', |
||||
messages: messages |
||||
}); |
||||
|
||||
var app = new Vue({ |
||||
el: '#app', |
||||
|
||||
i18n: i18n, |
||||
|
||||
data: { |
||||
notification: null, |
||||
|
||||
loading: true, |
||||
saving: false, |
||||
settingStatic: false, |
||||
loadingIndicator: '|', |
||||
uploadProgress: false, |
||||
|
||||
activeTab: 'status', |
||||
|
||||
status: { |
||||
systemID: 'loading...', |
||||
version: 'loading...', |
||||
resetReason: null, |
||||
stackTrace: false |
||||
}, |
||||
|
||||
wifiStatus: { |
||||
ap: { |
||||
enabled: false, |
||||
ip: '0.0.0.0' |
||||
}, |
||||
station: { |
||||
enabled: false, |
||||
status: 0, |
||||
ip: '0.0.0.0' |
||||
} |
||||
}, |
||||
|
||||
connection: { |
||||
hostname: null, |
||||
accesspoint: true, |
||||
station: false, |
||||
ssid: null, |
||||
password: null, |
||||
dhcp: true, |
||||
ip: null, |
||||
subnetmask: null, |
||||
gateway: null |
||||
}, |
||||
|
||||
system: { |
||||
pins: { |
||||
ledAP: null, |
||||
ledSTA: null, |
||||
apButton: null, |
||||
}, |
||||
ledCount: null |
||||
}, |
||||
|
||||
static: { |
||||
r: 0, |
||||
g: 0, |
||||
b: 0, |
||||
w: 0 |
||||
} |
||||
}, |
||||
|
||||
created: function() |
||||
{ |
||||
var self = this; |
||||
|
||||
self.notificationTimer = null; |
||||
self.disableSetStatic = false; |
||||
self.setStaticTimer = false; |
||||
|
||||
document.title = i18n.t('title'); |
||||
var hash = window.location.hash.substr(1); |
||||
if (hash) |
||||
self.activeTab = hash; |
||||
|
||||
self.startLoadingIndicator(); |
||||
self.updateWiFiStatus(); |
||||
|
||||
|
||||
// Sequential loading of all the settings makes sure
|
||||
// we don't overload the ESP8266 with requests, as that
|
||||
// can cause it to run out of memory easily.
|
||||
// This is a horrible way to implement it, but I don't feel like
|
||||
// including a big library or working out a clean short solution
|
||||
// at the moment, and it works :)
|
||||
self.loadStatus().then(function() |
||||
{ |
||||
self.loadConnection().then(function() |
||||
{ |
||||
self.loadSystem().then(function() |
||||
{ |
||||
self.stopLoadingIndicator(); |
||||
self.loading = false; |
||||
}); |
||||
}); |
||||
}); |
||||
}, |
||||
|
||||
methods: { |
||||
showNotification: function(message, error) |
||||
{ |
||||
var self = this; |
||||
self.notification = { |
||||
message: message, |
||||
error: error |
||||
}; |
||||
|
||||
if (self.notificationTimer != null) |
||||
clearTimeout(self.notificationTimer); |
||||
|
||||
self.notificationTimer = setTimeout(function() |
||||
{ |
||||
self.notification = null; |
||||
self.notificationTimer = null; |
||||
}, 5000); |
||||
}, |
||||
|
||||
hideNotification: function() |
||||
{ |
||||
var self = this; |
||||
self.notification = null; |
||||
|
||||
if (self.notificationTimer != null) |
||||
{ |
||||
clearTimeout(self.notificationTimer); |
||||
self.notificationTimer = null; |
||||
} |
||||
}, |
||||
|
||||
handleAPIError: function(messageId, error) |
||||
{ |
||||
var self = this; |
||||
|
||||
console.log(error); |
||||
var errorMessage = ''; |
||||
|
||||
if (error.response) |
||||
{ |
||||
errorMessage = 'HTTP response code ' + error.response.status; |
||||
} |
||||
else if (error.request) |
||||
{ |
||||
errorMessage = 'No response'; |
||||
} |
||||
else |
||||
{ |
||||
errorMessage = error.message; |
||||
} |
||||
|
||||
self.showNotification(i18n.t(messageId) + '\n\n' + errorMessage, true); |
||||
}, |
||||
|
||||
loadStatus: function() |
||||
{ |
||||
var self = this; |
||||
return axios.get('/api/status', { retry: 10, retryDelay: 1000 }) |
||||
.then(function(response) |
||||
{ |
||||
if (typeof response.data == 'object') |
||||
self.status = response.data; |
||||
}) |
||||
.catch(self.handleAPIError.bind(self, 'error.loadStatus')); |
||||
}, |
||||
|
||||
loadConnection: function() |
||||
{ |
||||
var self = this; |
||||
return axios.get('/api/connection', { retry: 10, retryDelay: 1000 }) |
||||
.then(function(response) |
||||
{ |
||||
if (typeof response.data == 'object') |
||||
self.connection = response.data; |
||||
}) |
||||
.catch(self.handleAPIError.bind(self, 'error.loadConnection')); |
||||
}, |
||||
|
||||
loadSystem: function() |
||||
{ |
||||
var self = this; |
||||
return axios.get('/api/system', { retry: 10, retryDelay: 1000 }) |
||||
.then(function(response) |
||||
{ |
||||
if (typeof response.data == 'object') |
||||
self.system = response.data; |
||||
}) |
||||
.catch(self.handleAPIError.bind(self, 'error.loadSystem')); |
||||
}, |
||||
|
||||
|
||||
applyConnection: function() |
||||
{ |
||||
var self = this; |
||||
if (self.saving) return; |
||||
|
||||
self.saving = true; |
||||
|
||||
axios.post('/api/connection', { |
||||
hostname: self.connection.hostname, |
||||
accesspoint: self.connection.accesspoint, |
||||
station: self.connection.station, |
||||
ssid: self.connection.ssid, |
||||
password: self.connection.password, |
||||
dhcp: self.connection.dhcp, |
||||
ip: self.connection.ip, |
||||
subnetmask: self.connection.subnetmask, |
||||
gateway: self.connection.gateway, |
||||
}, { retry: 10, retryDelay: 1000, headers: { 'Content-Type': 'application/json' } }) |
||||
.then(function(response) |
||||
{ |
||||
}) |
||||
.catch(self.handleAPIError.bind(self, 'error.applyConnection')) |
||||
.then(function() |
||||
{ |
||||
self.saving = false; |
||||
}); |
||||
}, |
||||
|
||||
applySystem: function() |
||||
{ |
||||
var self = this; |
||||
if (self.saving) return; |
||||
|
||||
self.saving = true; |
||||
|
||||
axios.post('/api/system', self.system, { retry: 10, retryDelay: 1000, headers: { 'Content-Type': 'application/json' } }) |
||||
.then(function(response) |
||||
{ |
||||
self.showNotification(i18n.t('rebootPending')); |
||||
}) |
||||
.catch(self.handleAPIError.bind(self, 'error.applySystem')) |
||||
.then(function() |
||||
{ |
||||
self.saving = false; |
||||
}); |
||||
}, |
||||
|
||||
startLoadingIndicator: function() |
||||
{ |
||||
var self = this; |
||||
|
||||
self.loadingStage = 0; |
||||
self.loadingTimer = setInterval(function() |
||||
{ |
||||
self.loadingStage++; |
||||
switch (self.loadingStage) |
||||
{ |
||||
case 1: self.loadingIndicator = '/'; break; |
||||
case 2: self.loadingIndicator = '-'; break; |
||||
case 3: self.loadingIndicator = '\\'; break; |
||||
case 4: self.loadingIndicator = '|'; self.loadingStage = 0; break; |
||||
} |
||||
}, 250); |
||||
}, |
||||
|
||||
stopLoadingIndicator: function() |
||||
{ |
||||
clearInterval(this.loadingTimer); |
||||
}, |
||||
|
||||
getWiFiStationStatus: function() |
||||
{ |
||||
if (!this.wifiStatus.station.enabled) |
||||
return 'disconnected'; |
||||
|
||||
switch (this.wifiStatus.station.status) |
||||
{ |
||||
case 0: // WL_IDLE_STATUS
|
||||
case 2: // WL_SCAN_COMPLETED
|
||||
return 'connecting'; |
||||
|
||||
case 1: // WL_NO_SSID_AVAIL
|
||||
case 4: // WL_CONNECT_FAILED
|
||||
case 5: // WL_CONNECTION_LOST
|
||||
return 'error'; |
||||
|
||||
case 3: // WL_CONNECTED
|
||||
return 'connected'; |
||||
|
||||
case 6: // WL_DISCONNECTED
|
||||
default: |
||||
return 'disconnected'; |
||||
} |
||||
}, |
||||
|
||||
getWiFiStationStatusText: function() |
||||
{ |
||||
if (!this.wifiStatus.station.enabled) |
||||
return i18n.t('wifiStatus.stationmode.disabled'); |
||||
|
||||
switch (this.wifiStatus.station.status) |
||||
{ |
||||
case 0: // WL_IDLE_STATUS
|
||||
return i18n.t('wifiStatus.stationmode.idle'); |
||||
|
||||
case 1: // WL_NO_SSID_AVAIL
|
||||
return i18n.t('wifiStatus.stationmode.noSSID'); |
||||
|
||||
case 2: // WL_SCAN_COMPLETED
|
||||
return i18n.t('wifiStatus.stationmode.scanCompleted'); |
||||
|
||||
case 3: // WL_CONNECTED
|
||||
return this.wifiStatus.station.ip; |
||||
|
||||
case 4: // WL_CONNECT_FAILED
|
||||
return i18n.t('wifiStatus.stationmode.connectFailed'); |
||||
|
||||
case 5: // WL_CONNECTION_LOST
|
||||
return i18n.t('wifiStatus.stationmode.connectionLost'); |
||||
|
||||
case 6: // WL_DISCONNECTED
|
||||
default: |
||||
return i18n.t('wifiStatus.stationmode.disconnected'); |
||||
} |
||||
}, |
||||
|
||||
updateWiFiStatus: function() |
||||
{ |
||||
var self = this; |
||||
if (!self.saving) |
||||
{ |
||||
axios.get('/api/connection/status', { retry: 10, retryDelay: 1000 }) |
||||
.then(function(response) |
||||
{ |
||||
if (typeof response.data == 'object') |
||||
self.wifiStatus = response.data; |
||||
}) |
||||
.catch(self.handleAPIError.bind(self, 'error.updateWiFiStatus')) |
||||
.then(function() |
||||
{ |
||||
setTimeout(self.updateWiFiStatus, 5000); |
||||
}); |
||||
} |
||||
else |
||||
setTimeout(self.updateWiFiStatus, 5000); |
||||
}, |
||||
|
||||
uploadFirmware: function() |
||||
{ |
||||
var self = this; |
||||
if (self.saving) return; |
||||
|
||||
self.saving = true; |
||||
self.uploadProgress = 0; |
||||
|
||||
|
||||
var data = new FormData(); |
||||
data.append('file', document.getElementById('firmwareFile').files[0]); |
||||
|
||||
var config = { |
||||
timeout: 360000, |
||||
onUploadProgress: function(progressEvent) |
||||
{ |
||||
self.uploadProgress = Math.round((progressEvent.loaded * 100) / progressEvent.total); |
||||
} |
||||
}; |
||||
|
||||
axios.post('/api/firmware', data, config) |
||||
.then(function(response) |
||||
{ |
||||
self.showNotification(i18n.t('rebootPending')); |
||||
}) |
||||
.catch(self.handleAPIError.bind(self, 'error.uploadFirmware')) |
||||
.then(function() |
||||
{ |
||||
self.uploadProgress = false; |
||||
self.saving = false; |
||||
|
||||
document.getElementById('firmware').reset(); |
||||
}); |
||||
}, |
||||
|
||||
deleteStackTrace: function() |
||||
{ |
||||
var self = this; |
||||
|
||||
return axios.get('/api/stacktrace/delete', { retry: 10, retryDelay: 1000 }) |
||||
.then(function(response) |
||||
{ |
||||
self.status.resetReason = 0; |
||||
self.status.stackTrace = false; |
||||
}) |
||||
.catch(self.handleAPIError.bind(self, 'error.stackTraceDeleteError')); |
||||
}, |
||||
|
||||
staticOff: function() |
||||
{ |
||||
this.static = { |
||||
r: 0, |
||||
g: 0, |
||||
b: 0, |
||||
w: 0 |
||||
}; |
||||
}, |
||||
|
||||
|
||||
staticChanged: function() |
||||
{ |
||||
var self = this; |
||||
if (self.loading || self.disableStaticChanged) return; |
||||
|
||||
if (self.setStaticTimer === false) |
||||
self.setStaticTimer = setTimeout(function() { self.setStatic(); }, 200); |
||||
}, |
||||
|
||||
setStatic: function() |
||||
{ |
||||
var self = this; |
||||
|
||||
if (self.settingStatic) |
||||
self.setStaticTimer = setTimeout(function() { self.setStatic(); }, 200); |
||||
|
||||
self.settingStatic = true; |
||||
self.setStaticTimer = false; |
||||
|
||||
|
||||
axios.get('/api/set/static', { params: this.static }) |
||||
.then(function(response) |
||||
{ |
||||
}) |
||||
.catch(self.handleAPIError.bind(self, 'error.setColor')) |
||||
.then(function() |
||||
{ |
||||
self.settingStatic = false; |
||||
}); |
||||
}, |
||||
}, |
||||
|
||||
computed: { |
||||
hasResetError: function() |
||||
{ |
||||
var self = this; |
||||
|
||||
/* |
||||
REASON_DEFAULT_RST = 0 normal startup by power on |
||||
REASON_WDT_RST = 1 hardware watch dog reset |
||||
REASON_EXCEPTION_RST = 2 exception reset, GPIO status won’t change |
||||
REASON_SOFT_WDT_RST = 3 software watch dog reset, GPIO status won’t change |
||||
REASON_SOFT_RESTART = 4 software restart ,system_restart , GPIO status won’t change |
||||
REASON_DEEP_SLEEP_AWAKE = 5 wake up from deep-sleep |
||||
REASON_EXT_SYS_RST = 6 system reset |
||||
*/ |
||||
return (self.status.resetReason === 1 || |
||||
self.status.resetReason === 2 || |
||||
self.status.resetReason === 3 || |
||||
self.status.stackTrace); |
||||
} |
||||
}, |
||||
|
||||
watch: { |
||||
static: { |
||||
handler: function(newValue) { this.staticChanged(); }, |
||||
deep: true |
||||
} |
||||
} |
||||
}); |
||||
} |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,201 +0,0 @@
@@ -1,201 +0,0 @@
|
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<title>RGBWifi</title> |
||||
<meta name="theme-color" content="#000000"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
<link rel="stylesheet" href="bundle.css"> |
||||
<script src="bundle.js"></script> |
||||
</head> |
||||
<body> |
||||
<div id="app"> |
||||
<div v-cloak> |
||||
<div class="notificationContainer"> |
||||
<div class="notification" :class="{ error: notification != null && notification.error }" v-if="notification != null" @click.prevent="hideNotification"> |
||||
<span class="message">{{ notification.message }}</span> |
||||
</div> |
||||
</div> |
||||
|
||||
<div id="container"> |
||||
<div class="header"> |
||||
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6N0E2MTY4NzJGQjFBMTFFQThERTJFM0JGMzk3MjRDRDUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6N0E2MTY4NzNGQjFBMTFFQThERTJFM0JGMzk3MjRDRDUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3QTYxNjg3MEZCMUExMUVBOERFMkUzQkYzOTcyNENENSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3QTYxNjg3MUZCMUExMUVBOERFMkUzQkYzOTcyNENENSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgI/6YAAAAfkSURBVHjazFpbbBRV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" /> |
||||
<h1>{{ $t('title') }}</h1> |
||||
<h2>{{ status.systemID !== null ? $t('systemID') + ': ' + status.systemID : '' }}</h2> |
||||
|
||||
<div class="wifistatus"> |
||||
<div class="connection"> |
||||
<div class="indicator" :data-status="wifiStatus.ap.enabled ? 'connected' : 'disconnected'"></div> {{ $t('wifiStatus.accesspoint.title') }} {{ wifiStatus.ap.enabled ? wifiStatus.ap.ip : $t('wifiStatus.accesspoint.disabled') }} |
||||
</div> |
||||
<div class="connection"> |
||||
<div class="indicator" :data-status="getWiFiStationStatus()"></div> {{ $t('wifiStatus.stationmode.title') }} {{ getWiFiStationStatusText() }} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div v-if="loading" class="loading"> |
||||
{{ $t('loading') }} {{ loadingIndicator }} |
||||
</div> |
||||
|
||||
<div v-if="!loading"> |
||||
<div class="warning" v-if="hasResetError"> |
||||
<p> |
||||
{{ $t('error.resetError') }} |
||||
</p> |
||||
|
||||
<p class="resetReason"> |
||||
{{ $t('error.resetReason.' + status.resetReason) }} |
||||
</p> |
||||
|
||||
<p v-if="status.stackTrace"> |
||||
{{ $t('error.stackTrace') }} |
||||
</p> |
||||
|
||||
<a class="button button-primary" href="/api/stacktrace/get" v-if="status.stackTrace">{{ $t('error.stackTraceDownload') }}</a> |
||||
<a class="button" @click="deleteStackTrace">{{ $t('error.stackTraceDelete') }}</a> |
||||
</div> |
||||
|
||||
|
||||
<div class="navigation tabs"> |
||||
<a class="button" :class="{ 'active': activeTab == 'status' }" @click="activeTab = 'status'">{{ $t('status.tabTitle') }}</a><a class="button" :class="{ 'active': activeTab == 'connection' }" @click="activeTab = 'connection'">{{ $t('connection.tabTitle') }}</a><a class="button" :class="{ 'active': activeTab == 'system' }" @click="activeTab = 'system'">{{ $t('system.tabTitle') }}</a> |
||||
</div> |
||||
|
||||
<div v-if="activeTab == 'status'"> |
||||
<!-- |
||||
|
||||
Status tab |
||||
|
||||
--> |
||||
<h3>{{ $t('status.title') }}</h3> |
||||
|
||||
<div class="slidercontainer"> |
||||
<input type="range" min="0" max="255" class="slider red" v-model.number="static.r"> |
||||
</div> |
||||
<div class="slidercontainer"> |
||||
<input type="range" min="0" max="255" class="slider green" v-model.number="static.g"> |
||||
</div> |
||||
<div class="slidercontainer"> |
||||
<input type="range" min="0" max="255" class="slider blue" v-model.number="static.b"> |
||||
</div> |
||||
<div class="slidercontainer"> |
||||
<input type="range" min="0" max="255" class="slider white" v-model.number="static.w"> |
||||
</div> |
||||
|
||||
<div class="buttons"> |
||||
<a class="button button-secondary" @click.prevent="staticOff">{{ $t('status.staticOff') }}</a> |
||||
</div> |
||||
</div> |
||||
|
||||
<div v-if="activeTab == 'connection'"> |
||||
<!-- |
||||
|
||||
Connection tab |
||||
|
||||
--> |
||||
<form @submit.prevent="applyConnection"> |
||||
<h3>{{ $t('connection.title') }}</h3> |
||||
|
||||
<check v-model.boolean="connection.accesspoint" :title="$t('connection.accesspoint')"></check> |
||||
<span class="hint">{{ $t('connection.accesspointHint') }}</span> |
||||
|
||||
<check v-model.boolean="connection.station" :title="$t('connection.stationmode')"></check> |
||||
<span class="hint">{{ $t('connection.stationmodeHint') }}</span> |
||||
|
||||
<label for="ssid">{{ $t('connection.ssid') }}</label> |
||||
<input type="text" id="ssid" v-model="connection.ssid" :disabled="!connection.station"> |
||||
|
||||
<label for="password">{{ $t('connection.password') }}</label> |
||||
<input type="password" id="password" v-model="connection.password" :disabled="!connection.station"> |
||||
|
||||
<check v-model.boolean="connection.dhcp" :disabled="!connection.station" :title="$t('connection.dhcp')" class="form-control"></check> |
||||
<span class="hint">{{ $t('connection.dhcpHint') }}</span> |
||||
|
||||
|
||||
<div class="suboptions"> |
||||
<label for="ip">{{ $t('connection.ipaddress') }}</label> |
||||
<input type="text" id="ip" v-model="connection.ip" :disabled="!connection.station || connection.dhcp"> |
||||
|
||||
<label for="subnetmask">{{ $t('connection.subnetmask') }}</label> |
||||
<input type="text" id="subnetmask" v-model="connection.subnetmask" :disabled="!connection.station || connection.dhcp"> |
||||
|
||||
<label for="gateway">{{ $t('connection.gateway') }}</label> |
||||
<input type="text" id="gateway" v-model="connection.gateway" :disabled="!connection.station || connection.dhcp"> |
||||
</div> |
||||
|
||||
|
||||
<label for="hostname">{{ $t('connection.hostname') }}</label> |
||||
<input type="text" :placeholder="$t('connection.hostnamePlaceholder')" id="hostname" v-model="connection.hostname" :disabled="!connection.station"> |
||||
<span class="hint">{{ $t('connection.hostnameHint') }}</span> |
||||
|
||||
<div class="buttons"> |
||||
<input type="submit" :disabled="saving" :value="saving ? $t('applyButtonSaving') : $t('applyButton')"> |
||||
</div> |
||||
</form> |
||||
</div> |
||||
|
||||
<div v-if="activeTab == 'system'"> |
||||
<!-- |
||||
|
||||
System tab |
||||
|
||||
--> |
||||
<form @submit.prevent="uploadFirmware"> |
||||
<h3>{{ $t('system.firmwareTitle') }}</h3> |
||||
|
||||
<input type="file" id="firmwareFile"> |
||||
|
||||
<div class="buttons"> |
||||
<input type="submit" :disabled="saving" :value="saving ? $t('applyButtonSaving') : $t('applyButton')"> |
||||
</div> |
||||
|
||||
<div v-if="uploadProgress !== false"> |
||||
{{ uploadProgress }}% |
||||
</div> |
||||
</form> |
||||
|
||||
<form @submit.prevent="applySystem"> |
||||
<h3>{{ $t('system.pinsTitle') }}</h3> |
||||
|
||||
<div class="horizontal"> |
||||
<label for="pinLEDAP">{{ $t('system.pinLEDAP') }}</label> |
||||
<input type="number" id="pinLEDAP" v-model.number="system.pins.ledAP"> |
||||
</div> |
||||
|
||||
<div class="horizontal"> |
||||
<label for="pinLEDSTA">{{ $t('system.pinLEDSTA') }}</label> |
||||
<input type="number" id="pinLEDSTA" v-model.number="system.pins.ledSTA"> |
||||
</div> |
||||
|
||||
<div class="horizontal"> |
||||
<label for="pinAPButton">{{ $t('system.pinAPButton') }}</label> |
||||
<input type="number" id="pinAPButton" v-model.number="system.pins.apButton"> |
||||
</div> |
||||
|
||||
<h3>{{ $t('system.ledStripTitle') }}</h3> |
||||
|
||||
<div class="horizontal"> |
||||
<label for="ledCount">{{ $t('system.ledCount') }}</label> |
||||
<input type="number" id="ledCount" v-model.number="system.ledCount"> |
||||
</div> |
||||
|
||||
<div class="buttons"> |
||||
<input type="submit" :disabled="saving" :value="saving ? $t('applyButtonSaving') : $t('applyButton')"> |
||||
</div> |
||||
</form> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="clearfix"></div> |
||||
</div> |
||||
<div class="version"> |
||||
{{ $t('copyright') }}<br> |
||||
{{ status.version !== null ? $t('firmwareVersion') + status.version : '' }} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<script language="javascript"> |
||||
startApp(); |
||||
</script> |
||||
</body> |
||||
</html> |
@ -1,207 +0,0 @@
@@ -1,207 +0,0 @@
|
||||
var messages = { |
||||
en: { |
||||
title: 'RGBWifi', |
||||
systemID: 'System ID', |
||||
firmwareVersion: 'Firmware version: ', |
||||
copyright: 'Copyright © 2020 Mark van Renswoude', |
||||
loading: 'Please wait, loading configuration...', |
||||
rebootPending: 'The system will be rebooted, please refresh this page afterwards', |
||||
|
||||
applyButton: 'Apply', |
||||
applyButtonSaving: 'Saving...', |
||||
deviceTime: 'Time: ', |
||||
|
||||
wifiStatus: { |
||||
accesspoint: { |
||||
title: 'AP: ', |
||||
disabled: 'Disabled' |
||||