diff --git a/README.md b/README.md index 5a451753..51c78b10 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ Model #|Name|Compatible Bulbs |FUT092|RGB/CCT|
  1. FUT012
  2. FUT013
  3. FUT014
  4. FUT015
  5. FUT103
  6. FUT104
  7. FUT105
  8. Many RGB/CCT LED Strip Controllers
| |FUT091|CCT v2|Most newer dual white bulbs and controllers| |FUT089|8-zone RGB/CCT|Most newer rgb + dual white bulbs and controllers| +|Casalux|CCT|sold by Aldi in Germany +|NLG|CCT|Neuhaus Lightning Group, Paul Neuhaus Other remotes or bulbs, but have not been tested. diff --git a/dist/index.html.gz.h b/dist/index.html.gz.h index 43c6cec5..de6bfd8d 100644 --- a/dist/index.html.gz.h +++ b/dist/index.html.gz.h @@ -1,2 +1,2 @@ -#define index_html_gz_len 12910 -static const char index_html_gz[] PROGMEM = {31,139,8,0,0,0,0,0,0,19,237,125,107,123,219,54,178,240,247,247,87,32,76,55,150,106,138,146,175,113,100,83,57,242,37,137,91,219,113,98,167,217,174,215,71,15,37,65,18,99,138,212,146,148,101,215,213,127,127,103,6,0,9,94,100,43,217,236,158,158,158,77,159,90,36,1,2,51,131,193,220,48,0,247,158,245,131,94,124,63,225,108,20,143,189,214,30,254,101,158,227,15,109,131,251,6,220,115,167,223,218,27,243,216,97,189,145,19,70,60,182,141,105,60,168,237,64,89,236,198,30,111,157,186,39,238,112,20,179,119,211,238,94,93,60,218,243,92,255,134,133,220,179,141,40,190,247,120,52,226,60,54,216,40,228,3,219,24,197,241,36,106,214,235,99,231,174,215,247,173,110,16,196,81,28,58,19,188,233,5,227,122,242,160,190,97,109,88,47,235,189,40,74,159,89,99,23,106,69,145,193,168,39,219,24,59,46,130,73,29,102,219,31,186,49,54,9,63,163,105,215,114,131,180,145,90,28,12,135,30,175,175,91,240,95,182,125,89,148,118,147,71,162,180,43,232,231,75,100,245,188,96,218,31,120,78,200,9,15,231,139,115,87,247,220,174,222,122,228,185,125,30,214,95,89,47,173,70,174,99,81,244,125,59,142,184,199,123,177,251,27,183,190,68,245,134,181,182,110,109,83,175,233,243,164,255,141,127,25,202,212,87,125,13,123,223,204,227,76,101,143,245,76,140,231,59,99,24,233,91,151,207,38,65,8,124,212,11,252,152,251,192,136,51,183,31,143,236,62,191,117,123,188,70,55,166,235,187,177,235,120,181,168,231,0,123,172,65,19,207,106,181,43,119,192,188,152,29,31,177,87,215,173,255,199,224,223,94,212,11,221,73,204,162,176,183,52,78,56,53,182,162,145,123,11,140,249,210,218,72,239,129,186,208,79,93,52,137,237,239,61,187,226,126,223,29,92,215,106,173,61,194,167,101,225,68,226,97,45,12,102,15,221,32,196,203,110,16,199,193,184,185,54,185,99,81,0,163,207,158,247,122,189,185,231,116,185,247,208,119,163,137,231,220,55,187,94,208,187,153,91,161,211,119,131,90,48,137,221,192,127,152,56,253,190,235,15,155,13,182,53,185,219,237,77,195,40,8,155,147,192,5,162,132,115,132,121,236,248,253,90,119,10,173,251,209,131,231,70,113,141,96,104,250,129,207,119,199,78,56,116,253,102,99,55,105,166,240,14,243,220,4,0,215,135,193,231,53,130,67,190,91,11,113,190,55,215,248,120,55,184,229,225,192,11,102,77,103,26,7,115,107,16,132,227,26,140,76,120,255,160,186,97,13,182,222,0,12,27,122,41,19,215,56,142,97,224,61,208,200,53,215,27,124,156,169,148,165,132,14,136,32,18,224,19,87,44,30,134,65,88,101,226,183,230,250,131,32,121,5,241,157,235,5,189,192,3,82,133,188,191,59,128,174,107,17,204,128,166,245,18,187,77,43,53,187,28,96,224,15,146,201,154,43,149,149,76,177,51,0,50,167,165,85,40,149,67,219,141,125,133,54,162,60,183,134,78,204,103,206,125,13,8,77,133,64,41,39,110,18,245,230,207,101,11,204,234,135,193,164,31,204,96,92,131,200,197,1,110,74,30,206,81,183,248,70,109,204,253,169,62,88,130,56,207,97,110,13,6,110,175,22,249,238,96,144,165,198,115,122,198,251,53,89,7,0,190,171,141,56,13,232,86,67,27,209,218,189,28,83,213,217,99,195,97,137,187,5,133,179,145,27,243,90,204,199,147,218,196,237,221,0,245,100,135,235,208,95,215,233,221,12,195,96,234,247,155,248,142,19,214,134,200,236,128,103,37,14,24,209,202,124,238,108,247,215,6,3,214,48,159,15,224,103,171,241,23,188,112,26,141,6,91,107,52,254,82,221,45,101,86,197,223,27,130,251,70,83,94,210,189,96,61,108,101,55,55,229,210,250,48,238,126,217,91,32,97,122,21,124,149,213,216,6,31,47,0,35,59,63,151,194,23,24,84,224,10,248,109,91,219,219,219,47,1,225,6,220,109,128,70,132,127,116,39,233,208,104,12,216,118,82,105,0,119,59,170,18,54,67,244,17,200,220,58,30,252,149,48,74,25,164,11,31,32,167,154,224,30,31,196,77,107,43,193,20,113,214,208,47,31,230,137,55,141,106,32,202,225,47,34,56,121,200,176,175,78,233,158,7,120,55,65,252,141,242,68,207,183,193,132,68,106,14,220,16,164,88,48,168,161,165,146,149,159,66,26,213,144,136,211,8,196,154,44,140,131,73,190,68,76,63,196,109,217,110,61,103,97,175,216,76,105,167,217,130,167,58,178,200,140,81,109,75,26,33,195,170,38,133,200,66,205,160,158,8,89,78,131,150,240,56,40,2,166,254,127,9,74,33,17,242,52,64,114,232,214,172,205,87,101,68,24,120,252,110,215,241,220,161,95,131,137,58,142,154,61,46,84,201,192,229,94,31,222,246,38,229,234,32,21,162,107,214,58,114,75,158,125,64,4,122,247,147,145,11,146,203,138,38,48,141,0,214,7,199,119,199,14,201,57,124,196,214,34,6,114,21,69,30,103,98,70,236,214,102,188,123,227,198,181,108,205,245,146,170,115,212,193,169,224,4,251,1,234,223,130,146,3,40,20,214,192,113,243,110,208,87,42,73,169,221,245,6,202,232,1,216,34,218,220,166,103,255,53,230,125,215,97,129,239,221,51,208,233,156,251,12,148,35,171,96,163,52,66,172,185,129,2,190,250,80,214,236,22,54,177,76,27,155,59,11,219,104,44,219,198,203,237,157,5,109,172,109,237,44,217,198,171,87,235,139,218,88,219,198,54,172,113,208,7,139,10,43,48,43,66,195,49,240,107,25,190,45,90,50,156,115,197,156,170,212,2,209,33,245,15,75,249,162,70,210,72,114,249,246,96,187,164,70,4,211,74,213,24,108,111,207,167,158,229,8,32,22,217,56,154,105,147,173,185,200,178,41,169,71,214,133,20,60,189,145,235,245,171,15,5,246,254,175,27,126,63,8,193,58,141,24,114,232,195,32,12,198,15,160,89,253,8,205,152,38,217,160,149,181,42,11,131,24,76,129,74,163,58,143,131,71,202,55,182,27,125,62,172,194,168,169,25,144,109,127,93,116,160,10,211,134,50,237,47,44,78,154,183,18,251,191,214,135,171,152,103,44,19,171,87,75,203,81,32,164,182,28,152,124,115,176,115,201,160,213,157,130,190,19,59,77,152,171,67,94,191,171,225,152,129,154,139,248,246,166,217,110,183,247,219,237,163,246,17,252,197,223,131,246,126,176,255,161,221,126,51,132,219,3,252,211,254,128,127,142,219,170,92,253,59,106,103,255,101,239,235,27,59,103,237,253,195,213,131,217,97,253,203,135,168,253,106,242,233,125,123,255,227,180,14,247,239,62,204,218,171,195,243,176,125,190,121,218,109,183,255,182,51,216,105,31,220,117,95,193,253,219,155,217,193,231,122,59,104,31,254,250,101,181,125,190,245,234,224,195,225,203,55,237,155,246,65,189,238,183,127,250,245,231,250,135,246,135,250,108,179,221,27,222,214,219,231,47,215,14,102,7,23,135,231,59,237,213,246,205,175,112,31,2,26,103,245,213,70,187,126,119,212,107,159,175,133,7,179,246,105,61,184,105,31,14,86,223,181,143,235,47,1,165,147,250,86,212,62,60,127,181,213,110,55,62,1,60,155,245,33,220,255,53,92,5,74,188,175,15,15,189,131,58,180,119,219,56,107,183,55,234,71,179,253,205,35,128,111,103,22,190,108,159,55,142,57,180,255,242,124,179,221,29,236,156,180,219,211,159,234,179,131,95,14,111,161,254,168,247,182,125,240,110,245,112,184,255,91,125,22,1,126,47,235,237,253,203,213,191,125,104,159,30,220,54,218,206,208,175,183,127,186,172,31,126,56,92,61,58,199,254,95,70,237,247,131,250,97,251,176,126,120,7,240,14,215,97,36,54,207,234,195,253,70,125,56,107,31,254,237,55,120,255,4,232,5,240,239,255,218,94,157,253,227,180,253,159,127,255,249,247,159,127,255,199,255,129,156,203,252,251,20,193,159,213,179,89,187,253,246,183,227,228,233,241,151,70,251,231,81,187,253,110,180,35,159,4,248,231,140,46,247,103,248,183,14,255,107,111,208,191,113,27,69,254,97,244,69,123,118,113,50,91,0,202,254,169,127,150,125,18,158,30,206,126,57,249,152,213,5,135,135,159,250,139,176,249,233,80,171,123,240,105,19,127,126,62,204,162,248,230,0,235,244,240,114,91,60,161,119,254,42,129,64,157,244,249,100,216,118,218,41,156,39,63,131,214,122,255,1,219,217,204,2,179,127,115,158,92,159,111,1,13,14,199,127,131,247,118,110,128,78,39,183,0,231,193,96,21,222,253,173,14,226,246,188,142,52,26,172,194,159,119,245,161,188,7,109,3,245,253,250,141,172,127,120,127,9,247,91,227,158,108,175,109,203,48,25,170,89,131,161,103,2,215,154,234,197,72,148,8,218,162,193,214,42,13,116,97,76,203,26,6,193,16,28,177,137,27,229,226,92,95,254,49,229,225,125,125,195,90,179,214,228,13,133,232,50,81,46,213,174,8,21,199,252,46,174,127,113,110,29,241,212,104,13,166,62,25,84,44,154,78,48,104,23,117,40,90,214,1,91,46,4,88,43,213,7,12,18,133,60,158,134,190,1,22,152,227,93,136,18,3,92,130,153,235,247,131,217,139,23,254,212,243,158,217,182,184,181,244,90,243,158,19,247,70,149,184,42,155,120,182,54,159,39,93,250,124,118,57,226,99,126,18,56,125,222,135,174,146,146,24,110,110,157,144,197,246,15,21,227,121,55,246,223,145,221,111,84,49,252,88,49,70,242,206,140,236,216,10,57,88,137,61,94,49,38,119,134,105,24,213,93,99,29,236,100,227,153,205,95,188,80,151,241,139,23,156,254,86,184,29,155,208,230,34,7,47,215,131,201,171,80,123,197,245,39,211,248,74,68,55,35,48,209,166,145,113,189,82,77,99,178,151,20,139,174,24,125,14,183,193,189,81,44,82,142,75,52,175,86,205,181,134,109,59,175,201,185,62,70,7,14,28,254,74,80,109,58,171,171,115,68,154,63,129,116,96,71,60,78,94,140,205,173,70,163,106,58,118,99,254,131,53,228,241,79,23,239,207,42,9,3,17,28,51,28,3,193,59,19,23,216,229,75,4,220,103,42,98,227,224,136,110,99,43,198,225,136,160,7,132,128,110,106,104,178,3,81,57,6,252,142,28,24,203,244,61,160,14,189,233,216,43,96,100,182,246,28,105,101,62,55,88,15,60,242,200,54,122,35,224,58,46,44,126,10,130,145,157,106,176,105,232,217,43,171,49,34,118,208,247,87,141,150,1,55,72,223,85,99,175,238,0,243,66,115,198,110,96,57,147,9,247,251,21,167,58,135,255,118,177,175,132,77,37,131,218,139,248,118,215,29,84,242,149,37,83,33,94,182,206,165,2,239,93,99,234,247,57,184,173,188,143,44,3,19,54,24,136,202,192,55,48,97,193,99,226,192,220,195,138,113,128,104,129,223,34,74,89,28,48,128,31,47,137,91,208,222,190,210,87,61,144,87,156,56,14,97,88,128,62,134,89,236,186,3,4,1,110,230,241,165,59,230,193,52,78,137,92,125,208,134,2,3,123,192,14,136,105,197,160,169,195,154,73,215,115,115,141,111,84,205,252,164,170,206,191,124,64,201,80,209,199,59,174,24,40,116,160,45,184,55,122,158,219,187,129,185,99,45,24,46,83,131,70,114,74,37,30,185,145,132,164,186,27,63,9,34,80,38,67,65,81,2,8,11,226,113,49,184,129,109,192,168,219,198,190,154,61,172,114,200,7,206,212,139,171,134,109,219,252,245,119,90,147,106,42,248,197,168,0,241,81,150,228,152,5,6,189,56,80,54,95,48,122,118,144,195,240,211,199,19,201,30,136,63,148,198,75,112,70,80,28,63,228,252,130,48,207,40,137,101,105,241,37,79,138,82,61,145,105,122,217,165,185,47,11,86,230,158,238,225,137,165,28,156,145,97,212,11,66,90,25,91,179,118,172,13,237,89,237,187,244,177,96,213,175,116,197,239,159,238,172,108,165,15,174,64,171,248,125,199,11,124,174,213,248,222,216,101,22,248,190,44,88,223,251,38,227,33,28,118,47,131,119,145,87,113,76,110,134,213,7,167,110,175,111,109,153,92,252,132,244,35,196,183,25,155,61,251,212,137,71,22,176,173,172,110,142,228,19,215,87,79,124,187,210,91,29,85,235,235,40,198,123,182,61,170,130,170,183,27,187,220,139,56,201,160,174,221,171,141,118,163,153,75,230,133,237,183,172,173,215,221,122,101,189,6,143,171,77,184,194,215,205,94,245,161,231,68,156,57,205,200,174,240,90,88,173,119,87,43,124,47,124,189,221,108,84,119,187,33,119,110,118,169,2,199,10,97,205,193,10,235,122,65,136,5,78,141,99,193,230,60,170,219,219,115,97,201,60,140,154,145,25,53,99,211,107,250,154,77,243,241,237,126,28,188,187,248,69,81,98,13,228,150,19,14,167,32,77,227,200,242,184,63,140,71,100,134,56,214,208,12,225,111,23,84,183,99,133,85,69,158,2,113,122,5,226,140,236,184,214,3,18,129,25,97,199,175,27,205,81,61,54,187,118,92,71,34,43,138,72,196,123,0,126,67,199,7,41,1,132,88,29,253,152,208,193,68,172,126,28,229,201,1,212,88,93,255,113,84,82,138,52,1,146,172,110,38,165,89,154,248,230,109,179,59,159,47,203,69,63,100,181,93,63,232,17,181,164,110,34,149,4,202,169,57,112,193,60,43,170,162,31,132,40,7,194,113,11,237,161,106,98,16,214,255,254,247,250,208,52,234,134,246,200,250,241,239,245,58,89,137,32,187,67,119,56,228,32,123,177,101,49,3,12,243,42,190,6,129,107,234,96,0,226,253,251,156,70,22,208,8,16,245,215,147,90,220,140,149,113,36,33,180,38,48,57,129,9,192,248,36,123,82,216,157,208,6,88,28,125,104,17,233,2,106,200,181,227,93,39,97,20,135,112,114,73,11,72,11,232,211,217,241,101,231,188,253,177,125,122,97,63,0,87,156,186,33,239,71,205,181,173,13,19,184,70,222,109,188,108,224,221,62,69,10,125,30,69,77,96,142,185,249,233,184,115,217,222,191,176,175,30,98,103,216,52,98,167,91,155,185,3,23,224,14,93,48,180,188,251,166,241,25,239,231,102,90,1,148,52,128,169,213,184,160,7,122,21,15,44,38,173,194,201,209,97,166,152,22,197,245,10,31,233,129,94,101,252,143,56,214,107,156,126,184,188,204,84,160,32,41,45,30,68,122,189,75,237,241,252,26,241,123,115,124,116,114,152,96,232,244,129,66,157,105,196,67,180,46,245,55,219,88,194,210,18,92,61,105,26,159,228,61,3,107,151,129,30,39,43,207,245,193,72,193,49,100,51,222,157,160,239,99,162,117,216,4,95,32,132,114,184,115,186,26,49,21,216,162,239,9,24,194,179,32,204,16,232,60,121,38,122,85,247,223,163,215,81,16,197,121,92,223,37,207,68,127,23,220,27,212,96,78,128,185,195,251,76,189,129,166,88,4,111,48,212,67,67,112,238,226,17,59,60,120,119,14,110,44,248,150,224,5,44,213,63,222,116,208,73,114,123,29,55,203,55,244,144,29,159,179,118,191,31,2,79,38,224,36,5,142,40,96,21,240,141,110,57,235,130,196,184,65,176,96,152,216,225,187,131,243,234,183,192,208,241,121,60,118,162,155,114,88,206,84,161,128,69,222,170,78,137,8,73,229,111,234,93,38,23,148,247,254,86,20,230,41,162,145,66,2,226,68,76,54,196,102,35,92,28,74,161,98,46,174,58,112,183,231,14,112,30,46,13,226,56,232,243,236,204,127,227,178,83,122,40,160,184,12,239,161,111,228,197,183,12,43,51,119,192,238,131,233,74,200,217,200,185,197,231,128,101,215,245,220,248,158,77,194,160,235,241,113,164,250,23,41,48,29,185,76,3,150,45,221,71,205,7,0,103,223,48,1,134,183,134,233,3,189,1,166,114,24,123,188,51,113,125,29,192,131,35,86,103,231,63,95,50,122,46,167,14,76,98,80,187,71,23,231,59,235,219,219,72,42,49,139,86,14,142,86,88,5,175,206,62,190,89,223,60,105,172,49,90,215,31,128,26,168,50,172,0,13,201,26,43,231,39,107,107,219,47,235,39,151,59,175,26,141,21,173,226,66,106,70,25,25,216,139,252,2,172,23,103,203,129,121,113,182,178,100,47,192,14,60,206,247,243,241,232,226,104,57,130,80,205,101,251,2,137,158,239,9,164,122,190,31,201,155,216,60,150,138,208,8,147,235,118,172,210,176,225,210,1,182,232,87,119,153,207,135,180,228,11,212,189,5,243,29,87,202,220,161,239,120,172,18,114,76,107,66,193,83,91,167,182,112,121,47,112,64,28,66,163,203,14,193,196,233,221,0,117,64,168,113,39,142,178,194,22,75,88,82,34,121,123,196,153,63,29,119,57,116,7,94,190,139,75,119,152,215,65,181,216,199,55,76,52,24,161,68,36,39,181,59,245,186,209,66,96,194,140,70,203,2,211,153,240,176,227,5,193,100,49,84,12,170,48,81,69,138,161,4,52,85,67,9,103,23,231,62,78,74,143,179,97,96,49,246,14,84,60,84,165,172,145,136,141,185,227,195,100,133,41,26,143,192,190,24,142,192,210,48,49,77,130,121,40,77,198,224,75,187,49,8,56,104,192,90,18,27,116,52,36,46,29,152,21,224,249,102,116,203,229,229,185,34,155,42,21,56,156,98,95,19,207,237,137,113,23,133,200,155,89,242,208,144,75,21,131,121,3,152,82,133,106,169,123,143,254,51,163,246,219,231,199,22,251,116,72,23,24,74,133,54,61,239,30,222,234,113,104,26,88,110,42,250,225,106,216,76,22,5,130,12,170,151,104,20,76,61,104,149,167,83,2,155,94,82,149,79,227,0,224,5,6,15,99,28,78,55,200,232,243,54,20,215,100,49,83,197,130,8,88,132,185,17,10,96,81,7,17,19,217,144,140,195,108,184,215,88,17,99,146,49,173,35,115,16,232,46,239,3,226,48,199,26,4,177,154,79,75,78,10,168,222,195,228,158,251,14,229,99,106,16,31,170,18,38,74,164,245,3,20,198,123,100,54,140,251,129,158,145,189,170,202,114,82,4,190,197,100,100,134,56,19,241,137,208,132,160,183,137,192,48,124,42,225,88,96,10,99,178,185,179,243,234,149,194,7,94,147,232,44,55,6,104,34,118,192,60,3,64,242,150,34,83,143,5,26,135,1,6,87,80,200,107,122,20,72,75,85,187,97,112,3,206,60,123,79,10,137,70,69,144,250,30,230,21,129,79,58,191,194,239,156,241,196,3,93,49,190,199,247,228,107,61,204,158,216,217,217,92,8,50,25,178,25,144,227,0,216,21,204,192,24,148,138,95,128,156,74,89,82,170,236,65,186,37,226,167,181,34,109,88,112,0,142,4,132,77,120,6,84,142,234,77,65,231,142,219,79,46,17,200,122,147,28,13,120,108,177,11,206,217,199,163,246,225,233,17,181,61,152,134,49,202,142,62,143,29,215,91,44,221,138,72,77,39,125,152,109,79,224,38,42,61,142,34,160,52,153,118,1,171,17,211,222,137,44,118,46,89,45,30,129,96,113,104,34,211,100,135,169,27,6,99,22,72,192,37,103,97,174,204,36,255,6,137,110,170,77,102,180,156,112,51,215,243,112,34,2,239,162,48,149,29,130,96,32,131,6,94,249,10,50,160,198,123,138,10,84,231,107,198,89,167,137,122,217,98,159,133,213,39,22,43,132,87,28,137,98,147,166,223,96,10,104,221,248,152,0,42,94,18,193,107,249,2,33,13,178,79,182,11,84,84,206,69,14,176,229,57,160,196,167,18,35,8,5,44,239,83,49,229,96,128,119,195,132,229,144,153,184,75,119,91,230,78,81,75,147,69,62,85,210,233,55,247,217,243,48,237,179,35,204,27,49,218,133,238,15,168,14,25,229,96,2,93,138,58,2,146,131,192,247,185,92,100,19,197,96,108,68,14,142,223,19,195,2,218,253,18,111,92,191,231,77,251,80,255,228,243,37,177,122,215,133,137,11,165,143,206,231,197,250,189,136,98,136,111,100,120,247,60,195,129,26,196,32,28,69,109,54,240,156,97,226,177,12,24,247,73,55,153,197,87,242,72,82,35,200,156,68,58,173,181,4,228,133,238,131,17,135,83,110,52,141,35,95,42,66,99,224,120,17,62,57,84,186,113,190,0,209,200,69,113,217,41,14,105,198,110,207,140,227,169,194,65,119,139,142,97,28,169,41,114,138,76,145,179,71,26,144,232,28,177,149,158,24,113,222,95,161,209,90,33,5,154,60,42,208,3,6,18,218,20,131,6,212,17,173,98,170,22,115,186,193,84,88,11,104,51,3,5,76,77,165,153,140,199,192,34,170,57,201,36,253,229,105,120,65,88,232,36,148,32,44,36,225,40,24,243,14,76,44,23,227,213,113,71,179,47,66,62,112,239,178,49,135,49,111,171,154,98,160,83,163,227,92,86,79,120,7,236,22,83,96,34,184,136,124,176,97,72,73,165,130,93,50,237,173,68,162,197,212,50,81,129,55,135,188,81,152,69,160,217,131,25,24,37,168,49,224,161,19,9,3,191,139,134,87,76,35,193,28,221,54,91,110,178,144,101,220,73,28,68,82,176,133,200,86,234,64,50,81,46,208,92,183,54,217,219,119,191,49,106,131,70,217,3,51,4,153,71,136,115,49,241,133,143,77,146,92,57,219,126,16,75,63,28,108,123,229,206,62,123,114,152,125,172,217,52,232,199,48,133,115,11,243,90,247,117,245,129,206,26,253,225,96,125,19,172,198,25,186,46,96,162,122,58,146,212,34,59,199,66,118,34,10,165,204,165,71,84,159,228,145,47,97,125,18,212,211,227,51,144,163,40,128,78,222,127,6,87,51,152,25,230,187,227,183,239,128,141,192,182,49,204,211,246,95,161,220,185,123,2,94,97,28,117,144,156,126,25,200,39,194,120,58,80,229,2,234,207,35,183,55,98,242,165,40,103,251,38,82,12,179,18,208,103,20,212,124,2,31,194,130,240,57,61,62,196,171,126,6,159,199,177,80,144,20,225,191,64,7,240,32,41,94,4,62,249,137,58,224,136,72,2,60,72,155,79,196,76,3,142,163,149,188,8,86,48,239,71,96,15,209,251,209,66,49,2,83,53,70,49,215,124,24,11,7,143,55,159,53,230,255,60,238,114,240,74,60,120,57,108,57,15,254,216,239,133,220,137,196,50,188,80,146,120,143,211,28,80,117,198,193,20,228,142,244,237,17,57,184,19,93,16,238,64,17,105,47,162,85,76,30,143,238,146,164,85,19,71,7,195,108,27,139,117,106,198,87,17,118,225,192,155,70,35,33,44,192,59,207,7,0,193,100,195,114,150,150,75,183,25,92,224,241,116,156,113,9,61,0,135,131,10,233,163,157,26,207,48,59,156,94,150,49,56,50,17,81,129,70,163,114,108,64,212,56,247,164,139,220,49,37,154,199,28,196,206,4,117,74,20,231,90,88,210,183,212,236,223,16,255,120,238,216,45,132,240,101,211,88,129,201,10,95,133,164,238,18,96,37,12,194,200,54,43,125,205,255,196,20,152,175,176,118,250,28,244,170,15,226,155,232,82,0,90,21,51,89,188,20,200,130,196,137,37,47,128,84,160,211,94,52,37,230,191,17,242,76,212,164,131,209,157,56,6,115,6,46,120,52,10,188,254,194,232,18,83,117,153,86,55,49,77,113,99,95,196,70,160,109,38,217,144,148,35,99,72,248,38,154,40,231,122,64,140,84,50,69,148,104,122,169,241,194,132,7,244,191,124,49,37,41,38,197,42,96,220,233,164,170,10,69,223,115,48,118,152,235,84,104,232,164,91,134,27,218,160,239,83,17,208,202,182,75,173,192,36,87,216,77,39,80,83,143,74,172,55,26,227,111,10,217,165,212,5,100,113,121,233,22,140,138,37,232,155,169,253,213,20,206,6,242,116,242,20,233,2,82,26,103,51,237,247,27,56,17,114,87,134,173,26,38,27,59,119,196,175,130,88,107,141,6,60,107,40,137,16,45,102,186,199,232,50,22,115,96,49,41,146,10,37,216,15,40,247,138,48,64,185,213,115,208,230,21,50,91,104,167,92,204,147,167,46,125,6,183,141,101,97,23,113,15,41,139,113,139,84,70,171,188,37,199,88,204,83,85,154,44,143,129,129,8,142,11,105,86,81,166,197,15,149,161,141,126,108,217,92,135,113,249,120,116,129,126,77,52,1,141,200,69,132,51,21,93,10,250,50,240,202,167,190,176,137,59,137,189,74,75,55,29,177,212,79,4,208,52,11,61,164,16,66,200,111,221,0,189,77,92,186,17,18,40,2,175,70,24,213,117,218,167,195,228,134,226,4,245,55,240,236,227,219,253,207,159,69,188,155,85,132,221,9,143,86,15,14,46,49,164,246,230,211,101,99,231,85,213,76,94,149,241,150,254,151,41,168,18,209,106,218,13,190,65,219,74,25,110,43,229,33,22,200,153,43,192,87,203,156,0,225,100,18,6,147,208,37,223,145,92,160,177,115,35,56,67,8,78,17,229,145,175,225,246,204,2,150,48,255,63,183,63,158,29,159,189,109,10,65,49,224,162,67,184,68,35,26,64,158,0,88,168,17,73,128,173,16,184,43,9,42,95,235,126,22,189,207,71,204,27,222,23,195,70,107,111,32,8,7,238,48,191,188,66,35,213,159,34,83,51,172,198,84,53,49,56,73,21,90,1,212,98,200,100,253,176,118,175,135,2,249,28,55,176,202,122,142,27,147,125,20,200,150,144,22,180,192,47,241,84,64,105,140,39,220,191,50,152,7,194,55,44,131,153,0,34,136,69,37,217,163,79,57,17,79,0,63,114,162,226,91,42,168,76,109,250,160,93,130,240,230,107,129,14,136,223,114,243,35,11,134,86,101,41,18,71,83,162,49,198,218,238,89,56,165,125,146,95,11,150,144,105,165,48,37,107,35,209,50,240,160,153,142,163,75,203,39,24,27,197,155,228,253,111,1,10,216,114,234,103,64,123,131,22,33,235,9,91,186,0,221,89,126,1,13,224,67,136,105,126,147,49,41,224,86,98,28,21,94,79,230,206,46,148,225,58,124,82,236,119,210,236,143,146,213,23,101,159,167,149,228,26,12,238,158,212,204,142,82,165,4,243,254,62,107,200,97,32,49,53,104,180,54,149,187,128,50,146,150,150,134,80,56,245,80,171,165,89,40,166,72,106,69,225,227,161,55,188,216,97,136,179,169,43,111,63,190,255,116,222,185,184,108,95,30,117,126,62,250,245,194,190,50,164,182,80,41,231,166,209,77,210,121,224,70,186,229,198,104,74,117,18,145,11,55,36,214,224,87,140,188,113,195,189,91,55,121,222,65,73,140,141,129,128,151,188,97,160,96,156,130,194,237,168,55,249,96,64,115,215,72,214,20,224,90,173,35,164,143,69,120,195,8,70,201,139,35,126,39,175,175,77,96,133,206,233,251,195,35,196,229,253,96,0,165,23,24,147,17,249,161,112,247,6,12,151,244,142,202,186,30,230,140,136,18,117,237,209,230,126,184,122,239,67,163,159,14,207,59,231,31,223,95,190,63,120,127,210,249,229,232,227,197,241,251,51,232,96,203,220,190,54,15,143,222,180,63,157,92,118,210,58,73,21,123,203,76,18,43,77,25,15,186,72,30,208,86,86,24,30,251,217,154,233,5,14,78,171,11,233,230,226,35,82,237,112,67,38,195,113,95,127,212,198,166,224,1,230,41,26,198,51,74,43,199,81,176,84,86,141,200,2,155,241,238,69,128,252,99,251,124,198,62,171,187,138,49,195,20,78,99,181,240,218,170,209,220,89,51,170,187,201,139,86,224,75,151,222,78,147,204,170,15,152,229,46,129,87,91,38,184,133,177,195,93,204,27,207,29,34,97,84,173,9,218,86,152,111,182,7,87,152,118,143,25,247,116,89,157,207,105,251,65,28,188,227,119,153,62,228,238,143,198,157,177,202,173,56,184,32,78,174,172,109,87,225,230,211,4,230,218,1,80,179,82,157,11,162,112,69,37,189,137,2,5,27,233,112,88,48,99,126,65,35,181,2,144,19,95,29,247,41,25,94,86,134,199,67,113,69,79,49,20,155,212,188,4,6,172,150,141,79,200,7,232,235,208,19,242,182,17,190,180,205,12,112,63,84,86,158,203,30,152,216,234,129,4,20,231,48,216,198,202,42,95,93,161,76,109,202,147,151,237,32,20,133,70,72,82,123,238,83,175,15,121,124,48,13,49,25,240,80,162,107,107,217,133,130,218,32,110,194,136,31,251,113,37,165,211,80,209,169,154,105,164,128,82,210,6,178,128,66,140,54,78,83,250,5,32,8,140,128,48,86,12,2,18,134,222,196,36,196,182,223,23,83,66,48,181,214,30,112,217,179,28,145,85,254,229,67,58,16,205,20,38,26,164,170,169,134,179,89,68,25,74,37,104,205,2,42,72,164,216,126,223,253,130,73,201,120,198,140,203,163,74,126,210,90,210,40,195,4,74,15,140,219,204,6,7,73,128,142,229,70,71,255,152,226,54,153,171,181,107,139,162,193,212,199,185,19,58,227,200,228,152,84,153,155,202,13,51,150,233,151,173,198,235,66,167,9,175,198,87,141,235,106,179,80,78,187,122,42,213,130,124,152,207,77,49,0,159,66,207,46,36,177,150,146,39,182,75,8,99,58,118,158,202,66,244,216,54,175,162,119,53,51,78,209,16,167,147,33,148,177,112,124,104,96,165,132,29,228,1,69,9,23,128,127,2,215,209,196,115,65,34,153,112,169,22,156,42,78,245,247,223,43,177,221,168,154,218,230,24,59,217,28,83,236,81,44,55,98,135,82,106,212,101,218,90,4,82,14,164,26,252,117,232,111,60,47,206,81,157,48,57,118,251,253,247,116,119,83,66,72,32,135,62,5,193,178,232,123,156,90,250,68,146,168,130,227,171,79,149,236,172,205,204,19,57,119,229,52,41,78,16,77,182,217,29,75,121,226,21,189,127,220,41,247,131,133,169,247,149,135,105,232,53,53,56,87,141,215,116,126,193,123,255,195,148,131,88,32,55,194,28,243,120,20,244,193,135,254,116,105,152,180,55,31,241,179,132,169,224,14,238,43,98,219,12,30,38,68,243,203,0,31,73,228,211,128,3,39,118,113,73,139,180,249,36,29,128,16,201,94,60,199,227,97,12,23,115,185,103,8,45,201,3,225,3,45,194,77,226,101,212,163,251,136,246,4,61,36,192,191,191,248,86,232,231,106,211,146,228,145,11,90,153,253,24,204,108,61,143,218,116,196,52,113,109,99,47,14,91,192,202,171,120,213,111,25,38,92,173,236,145,68,147,103,143,41,129,19,93,93,39,155,208,244,35,172,12,150,17,203,245,214,138,73,173,213,85,115,139,26,166,173,65,79,55,26,63,217,104,223,189,85,109,116,99,95,38,129,211,106,159,220,56,3,207,165,219,217,90,217,133,110,42,136,187,111,55,118,253,189,82,219,71,10,171,93,127,117,85,208,41,178,75,235,93,249,215,102,96,59,182,29,253,254,123,100,219,143,216,74,47,94,60,43,239,73,19,11,187,132,12,109,247,210,208,97,136,146,48,164,157,240,126,101,181,18,188,54,152,156,81,77,195,168,2,117,4,113,20,113,197,182,88,225,41,171,227,227,196,74,39,17,27,35,30,104,155,226,217,23,182,17,128,13,201,178,186,53,130,22,153,232,167,55,226,96,39,245,69,63,70,139,25,171,145,28,6,130,178,101,200,77,10,76,60,132,113,104,149,143,144,32,127,30,171,62,134,32,208,211,26,7,183,188,166,78,12,147,185,4,9,82,234,173,228,80,20,150,30,143,34,94,197,221,53,110,194,33,162,47,5,131,6,78,29,57,125,78,198,104,98,137,102,183,32,200,61,59,226,167,134,121,115,40,195,233,78,28,135,5,210,177,212,34,125,241,66,219,40,90,87,203,57,134,153,51,43,11,118,112,195,148,26,249,134,223,71,80,169,100,71,104,186,229,97,229,185,106,152,233,187,103,197,12,1,107,200,116,51,214,147,163,148,248,202,213,66,187,41,217,22,209,106,188,120,81,145,76,131,219,107,228,22,58,114,70,64,95,9,78,232,6,119,197,194,215,237,48,116,238,193,40,160,223,10,199,221,30,175,241,111,17,23,36,2,233,143,166,43,234,53,197,94,12,186,198,45,34,60,103,226,199,182,161,157,176,73,155,30,147,26,187,106,55,137,216,101,44,247,32,251,206,109,215,9,107,93,112,4,251,106,207,36,8,101,160,189,180,120,193,215,234,72,11,3,48,46,183,53,68,30,91,4,131,157,179,151,138,109,148,140,88,2,59,7,115,6,108,11,14,102,18,12,141,110,212,57,88,146,24,114,14,86,80,134,155,115,181,126,61,223,45,192,229,244,251,2,170,202,3,110,106,105,198,38,141,41,252,230,13,176,166,11,132,44,188,47,237,2,133,217,179,181,42,238,154,86,38,63,32,132,212,136,22,145,65,175,87,138,112,180,24,80,116,125,80,109,9,120,57,238,185,209,252,148,34,92,216,91,49,140,171,205,2,241,178,100,254,146,128,47,240,55,176,117,102,214,26,180,22,88,218,174,96,141,178,72,226,162,46,75,163,142,143,116,90,218,118,89,183,34,98,183,92,183,50,112,184,116,183,178,237,92,183,73,172,238,201,78,211,168,222,50,93,166,237,230,58,20,1,159,39,123,147,241,188,101,186,146,45,206,133,53,67,230,120,70,143,212,4,193,163,100,3,53,237,83,147,117,228,104,0,239,23,30,149,75,47,181,123,62,111,92,85,36,155,163,3,99,210,132,231,48,143,73,166,21,99,31,104,162,225,172,149,27,85,14,68,135,69,15,134,118,169,59,221,218,180,63,81,202,17,208,0,31,230,217,26,70,34,132,215,9,254,150,37,180,224,1,170,201,138,65,199,117,26,98,95,27,145,88,215,21,186,45,119,189,130,239,142,157,137,134,98,106,23,254,0,6,137,216,252,183,171,116,124,116,230,156,85,220,234,107,112,94,64,113,81,5,152,237,217,110,77,60,183,162,74,50,200,205,119,174,236,189,127,117,199,62,118,156,241,205,175,10,102,80,41,12,177,230,189,196,121,111,133,124,194,103,80,69,217,143,145,125,133,214,95,99,55,216,83,90,116,55,0,131,49,186,10,174,237,43,7,254,154,46,254,241,225,207,245,110,106,236,39,198,65,98,238,211,56,62,225,148,148,57,3,15,57,158,197,163,48,230,232,129,76,208,43,41,218,56,192,193,57,110,68,23,240,251,195,37,92,68,100,113,229,122,23,34,31,57,56,20,203,119,104,72,144,241,21,167,26,85,152,83,233,161,109,42,66,97,22,131,105,140,54,171,78,65,195,236,102,240,175,60,164,202,139,244,143,14,90,91,40,202,37,193,91,58,124,18,242,254,180,199,115,188,37,102,100,105,212,68,177,58,88,66,128,46,178,143,22,140,51,157,36,134,7,151,210,80,0,9,51,55,31,138,184,230,13,20,137,177,56,235,174,44,54,166,235,98,20,35,82,123,171,29,182,153,73,240,136,230,174,102,199,27,195,77,122,159,133,240,87,137,133,242,116,239,79,153,53,213,226,200,10,64,4,84,71,40,42,50,211,129,191,214,152,173,230,246,147,195,54,138,242,165,164,158,126,240,178,210,47,188,90,109,150,55,89,38,165,85,12,4,131,40,18,137,199,34,89,50,4,24,219,79,68,70,153,179,146,28,36,2,192,8,8,76,21,146,193,211,111,188,0,104,19,131,193,172,142,56,6,242,42,107,153,12,105,172,152,198,180,50,130,18,93,37,125,120,22,135,186,120,245,181,170,26,141,64,75,34,105,196,109,134,24,73,124,104,228,34,126,40,60,40,84,251,139,144,215,118,137,105,13,16,97,224,165,94,249,123,127,181,250,119,75,255,169,212,42,214,143,213,234,235,186,82,32,15,99,231,75,16,54,113,226,153,99,215,167,203,245,107,33,36,225,114,227,218,196,5,111,236,9,238,182,176,0,244,84,243,138,234,83,77,170,131,69,215,48,147,64,27,97,146,95,17,182,116,138,235,192,163,233,235,102,159,196,137,102,115,44,234,171,229,138,223,185,41,194,76,7,232,108,189,9,66,17,105,42,225,8,212,117,192,5,244,227,228,100,151,56,56,10,61,82,24,238,158,224,155,154,212,124,9,147,90,242,193,170,193,42,232,84,65,179,174,227,199,171,70,85,106,82,58,217,9,91,240,16,130,164,1,102,33,175,227,209,156,208,20,207,152,71,201,57,54,87,89,238,160,186,232,7,101,31,99,98,2,88,41,78,194,32,248,0,79,99,72,121,68,206,167,185,130,136,171,83,177,98,113,130,79,30,52,185,166,151,26,122,102,177,150,154,171,130,29,133,145,180,235,216,217,65,173,128,79,233,12,59,104,52,152,9,169,170,175,13,168,163,146,198,153,115,11,22,53,166,39,60,51,154,198,175,34,169,88,230,179,142,193,67,165,229,99,63,86,213,45,49,251,20,16,209,116,60,118,194,123,5,170,35,0,113,237,216,130,249,128,11,162,139,195,239,226,76,39,24,134,62,191,123,143,182,181,28,186,234,51,187,182,134,70,138,230,208,99,151,3,55,28,207,156,16,15,157,242,111,12,73,102,121,52,142,139,170,181,27,6,51,48,149,59,40,4,80,237,209,185,73,200,231,57,214,214,79,226,201,29,61,4,230,247,110,9,183,153,79,140,144,22,219,81,7,36,179,242,32,15,9,121,25,229,169,62,70,201,199,7,93,136,23,51,49,121,104,43,0,216,59,133,128,47,160,139,1,5,7,149,7,122,78,211,144,147,101,169,222,76,206,146,155,184,234,32,31,60,33,6,183,255,71,245,200,237,7,163,58,143,38,184,89,184,51,118,105,43,89,7,234,64,185,71,217,180,117,1,94,89,207,24,242,182,121,161,103,37,25,180,0,116,126,201,146,19,117,105,222,47,58,92,77,140,189,10,234,153,198,251,51,92,226,16,239,125,213,209,107,232,163,211,138,180,146,199,201,97,53,242,185,21,170,26,214,48,185,234,226,74,75,114,152,203,227,53,119,243,88,164,107,241,136,137,56,62,8,3,118,98,233,200,48,215,26,141,31,193,87,148,171,68,252,28,69,58,159,29,96,115,120,248,239,143,177,53,162,58,177,21,201,95,79,58,167,233,10,190,114,65,176,60,83,80,211,14,8,177,146,243,65,170,245,74,230,185,58,41,100,65,237,60,74,90,246,214,2,156,92,9,97,154,163,32,32,244,109,253,217,143,120,14,127,61,7,73,122,74,73,161,95,145,228,80,222,163,143,51,191,72,193,194,218,65,76,75,88,107,116,74,30,92,58,246,86,67,152,13,133,195,246,229,81,123,15,233,217,255,212,98,211,24,1,183,208,242,149,73,43,230,127,49,105,21,235,47,85,90,193,192,99,175,47,84,2,65,169,99,76,203,240,160,64,244,52,3,116,138,139,14,113,246,48,237,140,109,151,61,137,91,200,142,104,226,248,212,136,16,40,23,180,185,88,193,98,16,108,240,228,107,129,107,60,9,156,36,86,25,112,2,238,82,224,130,137,6,27,137,190,204,7,48,18,77,135,43,118,62,114,27,63,148,6,223,27,140,127,45,88,20,90,180,164,226,246,149,137,185,104,117,5,156,111,199,82,155,24,94,167,97,99,185,205,71,45,97,50,61,236,29,151,4,81,29,181,238,18,95,57,215,203,44,140,128,118,208,151,63,86,86,125,132,82,3,88,5,203,233,166,100,17,36,177,160,29,172,80,111,49,92,9,209,86,58,170,102,186,200,97,160,190,211,70,62,57,170,10,151,5,179,71,110,194,4,78,99,236,57,63,18,247,209,30,41,95,146,12,104,240,25,27,230,70,163,90,125,52,94,64,107,155,223,232,151,91,253,192,231,180,78,41,108,85,142,82,0,187,197,35,7,171,115,156,195,250,7,119,12,181,86,80,98,253,99,158,104,165,160,85,158,53,212,169,74,24,168,210,205,83,205,122,199,179,119,254,90,83,13,1,253,1,75,104,10,79,151,135,55,226,122,101,237,71,85,72,39,245,87,170,104,69,211,161,93,36,67,72,164,59,50,207,32,43,236,221,170,190,174,92,121,0,137,68,26,116,87,137,39,253,195,38,232,218,4,184,183,30,38,68,118,221,25,167,172,99,225,54,54,130,131,210,26,68,221,233,36,95,115,77,21,101,142,153,204,149,225,164,207,22,226,81,84,217,14,72,132,10,169,108,36,226,89,60,13,157,89,77,224,133,67,66,201,187,69,219,251,1,115,60,244,181,154,31,50,135,50,202,5,27,245,208,5,33,211,84,227,6,230,45,140,118,147,230,66,98,129,139,48,28,191,202,54,67,27,145,171,215,96,32,233,132,78,224,79,62,168,20,151,114,79,102,112,100,221,102,214,55,144,79,13,58,160,75,208,132,86,200,23,53,169,173,181,47,221,164,146,209,249,214,48,40,64,156,77,137,35,148,5,137,97,5,41,99,95,235,138,9,220,217,140,46,168,168,166,51,34,184,70,190,118,41,216,153,182,74,133,183,114,136,177,176,228,116,209,231,248,117,37,25,231,70,218,152,79,160,241,104,120,124,81,104,219,160,35,128,21,110,50,234,176,44,225,48,250,224,162,243,163,159,215,6,179,185,60,0,144,212,75,181,96,82,84,8,148,88,93,60,228,141,234,63,66,34,171,124,117,217,44,145,103,73,80,36,14,147,112,13,182,156,100,12,184,118,99,215,221,123,5,234,104,181,154,196,72,210,0,138,162,96,225,228,94,210,149,84,57,81,50,46,45,219,195,143,118,56,47,197,106,202,80,200,244,3,196,103,142,81,22,255,204,204,44,124,39,55,7,82,8,12,177,216,90,24,45,148,86,187,194,194,212,219,47,38,178,225,1,181,116,134,117,49,35,80,100,196,192,91,243,121,222,242,148,225,81,227,218,76,194,187,43,137,48,243,203,249,203,47,70,253,236,52,190,38,131,124,201,42,61,148,130,4,8,113,167,75,19,5,56,110,88,62,26,79,226,123,193,51,248,44,128,49,122,239,191,9,122,211,8,111,69,229,247,254,62,184,90,120,15,252,137,223,134,122,16,176,54,179,62,112,178,166,178,135,134,88,226,188,230,190,40,98,232,131,223,122,60,129,1,38,188,242,108,5,35,96,195,224,228,46,80,75,73,164,187,116,232,74,166,164,124,161,16,138,21,138,167,192,249,133,239,159,24,213,133,140,34,22,120,116,75,177,240,114,75,152,75,43,233,82,142,154,35,6,81,176,69,217,175,252,142,50,102,197,3,104,54,61,162,218,116,193,29,9,124,49,120,237,126,63,55,28,113,33,142,142,110,73,225,161,90,122,255,134,156,73,243,145,76,204,121,121,180,121,158,93,176,72,35,230,26,219,226,178,70,57,199,70,65,24,147,101,222,148,81,239,82,30,254,191,199,180,199,253,63,5,199,202,37,32,177,80,181,43,127,237,36,47,217,209,23,88,132,56,151,11,34,14,188,109,102,178,44,142,1,220,138,108,161,100,241,69,176,200,27,138,35,54,75,71,67,70,208,255,187,210,184,187,114,106,131,118,237,77,163,246,234,250,97,205,220,156,255,126,37,47,183,230,213,31,234,213,215,149,4,66,232,170,177,135,145,88,190,103,111,111,109,109,108,189,174,100,86,87,48,131,3,93,128,102,238,177,200,103,237,114,60,110,129,206,161,224,97,178,33,164,113,215,192,207,25,226,78,180,198,221,27,248,103,224,112,85,191,71,27,115,61,217,196,78,174,50,51,84,156,18,12,14,230,52,241,46,125,231,22,252,197,219,90,236,116,35,225,68,210,70,237,75,188,5,31,55,176,149,89,178,43,79,127,45,79,138,33,175,53,153,73,43,171,1,42,253,116,154,173,32,43,57,195,130,55,13,189,162,109,192,45,181,31,71,55,18,176,115,116,70,101,227,90,115,133,84,129,146,86,63,29,158,39,77,173,96,27,208,242,20,188,91,209,156,54,49,176,49,233,97,102,48,102,184,233,229,73,164,115,13,193,52,193,179,234,64,177,11,26,40,183,92,98,47,218,55,210,147,102,75,179,224,192,145,198,176,124,23,35,150,240,94,250,153,4,173,179,244,3,170,152,232,233,32,122,228,174,155,78,26,64,128,58,148,51,151,116,190,26,103,8,45,253,125,51,182,112,107,19,230,136,229,48,74,191,12,40,41,140,151,53,148,9,162,93,188,165,129,150,146,196,116,210,184,129,89,150,176,100,227,87,34,64,195,188,22,93,9,198,204,202,105,225,179,50,61,49,145,45,76,128,98,42,254,2,132,205,111,129,42,29,51,2,80,232,142,22,133,228,246,234,234,110,174,192,23,93,131,180,211,54,192,253,83,128,235,67,144,110,107,250,14,240,225,125,110,179,105,2,104,105,16,76,44,247,192,128,171,220,2,204,0,85,249,17,15,243,106,51,155,89,75,135,74,151,231,44,231,49,195,180,101,125,244,97,114,56,115,49,121,147,72,82,181,116,238,149,78,153,194,12,23,115,184,232,213,69,53,250,108,33,211,190,94,168,121,52,114,101,88,135,34,115,77,222,177,138,58,165,219,155,162,106,190,36,154,118,199,110,92,156,165,165,126,103,49,147,201,26,57,81,206,203,171,22,243,162,48,0,161,78,168,119,236,60,4,60,116,193,61,248,141,139,228,211,234,46,29,252,190,56,249,130,95,137,245,179,235,100,5,54,151,190,234,84,95,59,214,100,26,141,18,213,218,76,222,177,175,64,11,139,167,215,218,83,249,136,242,49,50,135,205,52,175,174,145,61,237,31,44,224,24,164,224,67,113,178,98,29,19,212,62,175,228,115,75,192,227,214,182,82,40,156,197,192,82,216,10,126,43,6,6,8,12,105,221,148,120,247,200,158,37,3,149,154,1,101,244,46,51,159,22,242,216,66,80,180,47,168,46,92,43,134,106,123,46,217,145,229,145,111,205,230,164,179,76,105,197,207,29,162,175,29,7,1,10,185,202,3,157,66,143,121,192,77,3,195,228,38,101,3,231,60,223,68,66,27,98,251,132,227,130,24,104,10,95,123,142,110,183,140,58,8,43,78,69,178,158,203,227,7,50,97,167,210,21,250,106,38,169,188,82,18,172,144,17,138,63,246,169,252,25,48,114,30,118,17,158,66,50,78,186,151,14,96,92,148,27,117,5,115,47,126,241,226,89,102,51,215,139,23,153,109,142,37,62,220,31,247,3,2,233,39,25,208,106,76,13,200,46,134,81,68,54,186,60,158,25,76,2,221,245,80,124,152,125,44,95,17,159,85,135,34,185,115,66,168,30,113,99,228,234,202,237,190,89,115,175,23,120,158,51,137,146,199,78,8,195,99,39,9,242,73,113,43,235,21,134,53,60,122,207,104,137,133,94,68,192,29,210,178,130,244,118,88,166,58,205,76,104,206,104,125,151,226,100,239,6,3,171,54,139,163,72,232,151,166,110,221,104,105,219,2,132,65,75,123,79,50,228,21,8,178,34,194,5,59,31,203,225,199,104,101,13,234,68,207,100,41,43,196,94,150,172,121,249,220,82,178,32,177,182,115,77,83,124,87,120,22,116,249,132,199,77,139,131,36,40,5,9,91,217,101,201,132,126,105,103,170,181,36,60,169,245,78,95,81,48,242,53,202,249,40,121,159,129,133,163,177,32,102,157,212,64,129,79,130,201,116,98,139,51,60,196,67,126,7,176,244,57,160,38,14,242,104,137,207,66,100,134,190,7,211,46,214,198,221,209,71,37,1,8,63,151,149,31,20,130,189,38,190,88,188,212,200,100,94,80,195,211,22,183,25,130,9,252,34,14,34,193,193,35,183,19,112,220,91,87,204,197,226,56,210,234,137,92,151,145,158,162,174,52,150,0,79,85,151,128,145,98,161,195,109,164,106,89,192,64,73,151,203,246,80,75,18,129,100,79,162,125,246,70,62,94,208,15,46,219,23,54,211,149,118,35,106,214,242,19,97,159,30,167,173,163,187,185,144,71,133,149,75,95,61,203,240,109,250,88,164,50,22,62,138,183,36,15,183,232,51,96,123,221,2,27,118,19,30,212,186,194,175,244,45,197,147,79,125,155,175,85,242,241,181,50,138,136,43,177,139,78,252,5,169,180,64,105,16,160,137,135,174,215,193,221,195,84,154,166,160,74,101,92,195,162,188,148,172,69,227,218,6,98,148,122,199,89,205,95,222,150,209,18,225,38,118,6,70,176,242,154,149,11,152,190,145,52,66,102,9,158,147,198,161,131,3,10,78,137,51,68,45,203,34,65,32,252,183,12,250,217,75,29,191,165,145,56,238,231,225,23,28,164,160,63,238,103,5,147,150,208,155,74,167,69,200,97,227,25,188,142,104,191,246,104,218,197,221,218,5,164,138,32,111,102,17,209,115,110,169,155,204,206,114,193,211,132,91,175,23,155,225,176,59,195,63,29,188,25,76,227,198,206,43,250,121,181,150,165,131,140,110,27,45,178,166,18,100,22,39,120,168,23,22,164,120,148,231,97,200,83,101,212,198,212,214,226,189,168,106,17,232,169,141,168,107,48,171,196,218,180,157,36,23,180,216,90,130,192,99,96,124,143,254,215,161,183,245,127,91,111,192,188,108,227,223,214,27,240,29,219,92,170,55,150,225,201,148,3,5,195,125,15,88,182,0,150,173,63,8,44,219,0,203,246,31,4,150,151,0,203,203,63,8,44,59,0,203,206,191,141,59,27,208,91,219,243,146,254,50,26,241,17,73,170,9,61,10,79,182,62,242,113,0,106,6,87,239,202,228,158,102,98,44,216,159,46,233,91,176,46,178,222,216,2,91,67,192,211,194,32,64,170,66,30,177,129,165,239,179,208,16,38,225,44,16,67,219,73,167,24,234,130,236,2,30,30,56,152,177,110,245,234,160,49,178,181,15,14,46,23,86,150,42,38,177,113,18,9,159,237,109,245,137,54,10,47,44,172,156,176,173,86,95,156,144,200,234,108,127,231,209,247,72,249,229,222,123,181,134,239,173,63,250,222,122,163,248,222,122,35,111,163,61,198,135,139,172,146,181,245,71,116,124,58,87,51,218,28,126,117,141,78,192,45,219,213,104,171,245,110,10,12,7,191,95,11,234,118,46,24,144,38,203,45,44,144,89,116,229,254,125,49,23,56,101,118,249,83,160,232,2,144,23,83,77,51,127,190,142,74,23,73,70,249,55,19,75,72,58,21,58,161,108,61,166,229,233,177,66,234,186,0,93,212,196,15,237,162,172,203,62,115,238,192,242,105,228,158,42,139,168,209,48,190,141,78,146,169,74,77,197,175,32,25,37,88,178,203,52,111,253,155,41,167,61,165,163,76,107,148,101,159,48,219,114,132,213,19,232,255,53,148,253,186,89,14,180,72,211,238,191,137,52,212,204,114,200,139,44,254,239,141,246,87,49,131,56,224,245,219,17,77,21,93,146,50,154,58,25,110,214,144,72,114,90,89,102,87,75,210,143,70,159,236,170,183,212,216,69,87,66,8,246,242,185,195,92,223,3,47,123,161,128,206,11,103,108,233,177,64,109,222,160,208,83,100,69,31,242,9,37,26,116,104,74,24,173,207,248,147,218,5,66,17,17,133,23,246,135,38,2,52,250,142,35,27,22,186,71,183,246,177,190,125,218,169,36,76,140,51,188,206,117,190,44,154,114,87,211,99,93,77,28,55,124,58,232,57,141,100,208,243,28,170,127,35,48,242,144,161,71,96,153,250,203,64,163,31,53,196,62,209,43,249,177,65,35,97,2,191,147,199,121,251,107,120,46,203,99,218,155,72,28,156,241,240,87,248,238,95,199,129,120,45,15,7,127,108,148,228,73,208,146,39,50,218,189,140,70,4,79,89,56,95,127,145,22,232,12,105,23,75,179,225,159,7,157,209,145,53,248,5,156,60,83,243,187,120,89,248,21,199,229,44,114,93,126,169,94,114,138,34,157,155,255,140,68,41,14,243,191,216,71,193,65,120,60,50,255,132,87,194,178,57,208,89,75,249,219,136,82,22,217,250,31,226,127,113,38,60,126,196,165,35,209,251,158,51,224,2,27,254,142,83,224,17,232,137,62,255,14,238,47,56,74,248,54,69,21,75,147,7,52,166,112,60,202,119,81,235,76,125,215,241,130,97,65,90,58,94,109,113,73,105,56,92,20,45,181,158,42,118,106,8,42,130,203,50,118,147,247,141,214,11,58,142,123,55,37,203,104,61,219,131,28,84,245,245,105,177,127,2,173,163,245,242,73,160,242,114,158,180,151,152,110,51,97,66,71,9,61,69,162,71,107,47,166,79,211,164,121,68,8,209,94,140,200,183,240,156,71,184,76,2,223,135,123,117,184,195,39,248,137,210,243,32,140,147,7,231,97,128,1,26,143,201,253,240,73,65,186,44,155,87,245,10,28,220,144,66,172,136,48,230,118,167,44,173,238,133,223,141,253,225,145,125,120,37,16,64,122,149,33,175,246,176,96,85,172,131,191,136,59,252,34,93,158,242,51,211,197,134,23,126,55,154,236,230,56,55,183,162,245,231,99,217,116,173,122,41,94,45,82,105,25,99,159,24,87,172,194,210,138,153,78,217,92,208,80,100,43,45,178,42,147,157,154,23,162,218,215,14,114,18,199,194,3,91,25,253,173,205,156,144,78,31,16,119,116,170,172,92,139,204,236,199,90,106,40,10,175,201,13,96,37,195,177,217,186,20,21,153,60,84,156,85,232,75,64,152,197,172,62,205,90,133,81,217,212,152,49,119,250,248,34,36,211,149,232,252,194,239,159,143,127,11,43,217,95,37,114,75,248,192,32,51,190,219,106,123,152,168,200,98,252,102,138,195,146,248,96,93,75,12,145,135,102,164,188,108,209,246,219,150,88,13,199,207,56,220,7,83,204,127,77,211,65,88,151,15,240,83,7,211,201,48,164,83,166,44,134,11,208,23,193,152,139,79,62,136,2,252,94,145,248,184,149,248,234,131,216,36,27,153,242,19,58,248,169,159,94,16,134,211,137,248,152,37,37,60,209,46,73,139,29,15,196,215,18,70,148,208,6,175,144,222,22,237,152,192,89,224,42,35,208,242,61,65,53,83,114,93,20,139,239,66,113,182,0,5,139,252,155,101,166,19,145,241,80,82,40,233,136,117,93,223,193,20,71,245,25,97,158,82,86,157,171,161,157,169,241,244,105,26,160,115,221,248,221,180,203,212,3,134,187,139,145,210,22,75,211,41,28,230,107,167,183,116,239,25,165,243,209,183,62,196,169,45,70,33,245,194,96,130,241,4,198,196,17,167,200,10,209,84,81,8,49,185,87,159,148,20,68,165,239,204,56,228,251,78,232,3,44,216,32,17,176,27,56,97,255,25,14,117,194,170,226,147,57,174,175,125,68,39,57,226,181,71,223,70,146,137,152,140,78,224,40,25,89,32,27,113,7,129,131,29,136,38,63,93,236,235,227,148,17,190,117,53,18,6,19,27,202,241,100,62,76,117,224,126,79,204,81,145,63,238,132,49,73,214,26,78,206,236,156,209,115,229,114,235,65,90,145,84,250,186,217,169,100,249,36,116,233,216,150,214,62,157,62,195,50,242,159,210,248,100,156,71,92,59,32,249,39,152,189,214,197,188,37,74,175,64,113,69,65,229,166,31,248,188,184,88,191,100,198,54,230,17,98,198,27,104,47,121,245,109,8,41,229,4,194,136,184,61,25,225,82,205,182,20,6,82,164,235,202,173,32,206,6,192,22,79,202,216,252,18,93,185,180,61,64,73,172,69,52,30,209,160,122,154,211,159,91,169,44,171,75,144,34,249,35,137,212,123,163,144,84,189,220,59,152,218,212,186,90,207,159,211,149,167,118,246,60,35,131,26,60,161,103,197,246,84,228,88,68,72,31,111,73,101,186,8,150,75,154,42,174,149,38,199,126,9,170,194,21,250,23,226,140,172,164,15,241,218,71,33,134,217,33,209,111,185,166,146,239,54,119,156,120,65,115,103,1,101,195,201,246,38,33,127,172,61,57,52,244,21,22,145,70,228,44,168,142,167,87,216,226,60,44,237,125,220,33,129,7,97,25,173,95,92,80,27,192,104,66,199,100,115,77,75,91,69,34,103,15,221,74,117,96,54,217,238,105,27,245,127,122,146,151,231,244,253,249,38,187,72,82,100,47,216,71,105,255,124,173,75,180,55,218,72,230,157,248,46,125,174,105,173,193,141,214,215,88,146,139,53,103,190,225,44,103,46,4,168,4,197,141,188,133,144,130,245,191,206,66,16,68,251,223,96,34,124,87,203,224,15,39,58,202,210,174,255,124,130,67,164,182,39,217,228,79,11,139,52,140,46,72,147,91,242,124,244,59,25,196,68,99,166,157,133,147,11,248,162,247,6,115,82,204,113,39,124,100,249,238,27,59,32,63,50,115,238,61,176,5,186,150,248,1,76,38,54,144,149,45,138,253,97,184,179,46,195,131,168,223,91,255,31,125,250,64,3,255,181,0,0}; \ No newline at end of file +#define index_html_gz_len 13044 +static const char index_html_gz[] PROGMEM = {31,139,8,0,0,0,0,0,0,10,237,125,107,119,219,56,146,232,247,123,206,253,15,8,211,19,75,109,138,146,159,113,100,75,89,249,145,196,211,142,227,196,78,247,244,120,124,125,32,9,146,24,83,164,134,164,44,187,221,250,239,183,170,0,144,224,67,182,146,201,204,246,206,78,250,180,69,18,32,80,85,40,212,11,5,112,239,89,63,232,197,247,19,193,70,241,216,107,239,225,95,230,113,127,216,178,132,111,193,189,224,253,246,222,88,196,156,245,70,60,140,68,220,178,166,241,160,182,3,101,177,27,123,162,253,222,61,113,135,163,152,189,155,118,247,234,242,209,158,231,250,55,44,20,94,203,138,226,123,79,68,35,33,98,139,141,66,49,104,89,163,56,158,68,205,122,125,204,239,122,125,223,233,6,65,28,197,33,159,224,77,47,24,215,147,7,245,13,103,195,121,89,239,69,81,250,204,25,187,80,43,138,44,70,61,181,172,49,119,17,76,234,48,219,254,208,141,177,73,248,25,77,187,142,27,164,141,212,226,96,56,244,68,125,221,129,255,178,237,171,162,180,155,60,18,165,93,65,63,95,34,167,231,5,211,254,192,227,161,32,60,248,23,126,87,247,220,174,217,122,228,185,125,17,214,95,57,47,157,70,174,99,89,244,125,59,142,132,39,122,177,251,155,112,190,68,245,134,179,182,238,108,83,175,233,243,164,255,141,127,26,202,212,87,125,13,123,223,204,227,76,101,143,245,76,140,231,243,49,140,244,173,43,102,147,32,4,62,234,5,126,44,124,96,196,153,219,143,71,173,190,184,117,123,162,70,55,182,235,187,177,203,189,90,212,227,192,30,107,208,196,179,90,237,210,29,48,47,102,199,71,236,213,85,251,255,254,31,6,255,246,162,94,232,78,98,22,133,189,165,145,194,185,177,21,141,220,91,224,204,151,206,70,122,15,228,133,142,234,178,73,234,96,239,217,165,240,251,238,224,170,86,107,239,17,70,109,7,167,146,8,107,97,48,123,232,6,33,94,118,131,56,14,198,205,181,201,29,139,2,24,127,246,188,215,235,205,61,222,21,222,67,223,141,38,30,191,111,118,189,160,119,51,119,66,222,119,131,90,48,137,221,192,127,152,240,126,223,245,135,205,6,219,154,220,237,246,166,97,20,132,205,73,224,2,89,194,57,2,61,230,126,191,214,157,66,235,126,244,224,185,81,92,35,24,154,126,224,139,221,49,15,135,174,223,108,236,38,205,20,222,97,158,155,0,224,250,48,252,162,70,112,168,119,107,33,206,248,230,154,24,239,6,183,34,28,120,193,172,201,167,113,48,119,6,65,56,174,193,216,132,247,15,186,27,214,96,235,13,192,176,97,150,50,121,141,35,25,6,222,3,141,93,115,189,33,198,153,74,89,74,152,128,72,34,1,62,113,197,17,97,24,132,85,38,127,107,174,63,8,146,87,16,223,185,89,208,11,60,32,85,40,250,187,3,232,186,22,193,28,104,58,47,177,219,180,82,179,43,0,6,241,160,216,172,185,82,89,201,20,243,1,144,57,45,173,66,169,26,218,110,236,107,180,17,229,185,51,228,177,152,241,251,26,16,154,10,129,82,60,110,18,245,230,207,85,11,204,233,135,193,164,31,204,96,92,131,200,197,1,110,42,46,206,81,183,248,70,109,44,252,169,57,88,146,56,207,97,118,13,6,110,175,22,249,238,96,144,165,198,115,122,38,250,53,85,7,0,190,171,141,4,13,232,86,195,24,209,218,189,26,83,221,217,99,195,225,200,187,5,133,179,145,27,139,90,44,198,147,218,196,237,221,0,245,84,135,235,208,95,151,247,110,134,97,48,245,251,77,124,135,135,181,33,50,59,224,89,137,3,70,180,178,159,243,237,254,218,96,192,26,246,243,1,252,108,53,254,132,23,188,209,104,176,181,70,227,79,213,221,82,102,213,252,189,33,185,111,52,21,37,221,75,214,195,86,118,115,83,46,173,15,227,238,151,189,5,50,166,87,193,87,89,141,109,136,241,2,48,178,243,115,41,124,129,65,37,174,128,223,182,179,189,189,253,18,16,110,192,221,6,232,68,248,71,119,138,14,141,198,128,109,39,149,6,112,183,163,43,97,51,68,31,137,204,45,247,224,175,130,81,201,32,83,248,0,57,245,4,247,196,32,110,58,91,9,166,136,179,129,126,249,48,79,188,105,84,3,97,14,127,17,193,201,67,134,125,77,74,247,60,192,187,9,226,111,148,39,122,190,13,38,37,82,115,224,134,32,197,130,65,13,109,149,172,252,148,210,168,134,68,156,70,32,214,84,97,28,76,242,37,114,250,33,110,203,118,235,241,133,189,98,51,165,157,102,11,158,234,200,33,67,70,183,173,104,132,12,171,155,148,34,11,53,131,126,34,101,57,13,90,194,227,160,8,152,254,255,37,40,133,68,200,211,0,169,161,91,115,54,95,149,17,97,224,137,187,93,238,185,67,191,6,19,117,28,53,123,66,170,146,129,43,188,62,188,237,77,202,213,65,42,68,215,156,117,228,150,60,251,128,8,244,238,39,35,23,36,151,19,77,96,26,1,172,15,220,119,199,156,228,28,62,98,107,17,3,185,138,34,79,48,57,35,118,107,51,209,189,113,227,90,182,230,122,73,213,57,42,225,84,112,130,5,1,245,111,65,201,1,20,26,107,224,184,121,55,232,107,149,164,213,238,122,3,101,244,0,172,17,99,110,211,179,255,26,139,190,203,89,224,123,247,12,148,186,16,62,3,229,200,42,216,40,141,16,107,110,160,128,175,62,148,53,187,133,77,44,211,198,230,206,194,54,26,203,182,241,114,123,103,65,27,107,91,59,75,182,241,234,213,250,162,54,214,182,177,13,103,28,244,193,166,194,10,204,137,208,116,12,252,90,134,111,139,150,140,16,66,51,167,46,117,64,116,40,253,195,82,190,168,145,52,82,92,190,61,216,46,169,17,193,180,210,53,6,219,219,243,169,231,112,9,196,34,27,199,48,109,178,53,23,89,54,37,245,200,186,80,130,167,55,114,189,126,245,161,192,222,255,117,35,238,7,33,216,167,17,67,14,125,24,132,193,248,1,52,171,31,161,25,211,36,43,180,178,86,101,97,16,131,41,80,105,84,231,113,240,72,249,198,118,163,47,134,85,24,53,61,3,178,237,175,203,14,116,97,218,80,166,253,133,197,73,243,78,226,1,212,250,112,21,139,140,101,226,244,106,105,57,10,132,212,150,3,147,111,14,134,46,25,180,166,91,208,231,49,111,194,92,29,138,250,93,13,199,12,212,92,36,182,55,237,78,167,179,223,233,28,117,142,224,47,254,30,116,246,131,253,143,157,206,155,33,220,30,224,159,206,71,252,115,220,209,229,250,223,81,39,251,47,123,95,223,216,57,237,236,31,174,30,204,14,235,95,62,70,157,87,147,207,31,58,251,159,166,117,184,127,247,113,214,89,29,158,133,157,179,205,247,221,78,231,175,59,131,157,206,193,93,247,21,220,191,189,153,29,252,82,239,4,157,195,95,191,172,118,206,182,94,29,124,60,124,249,166,115,211,57,168,215,253,206,159,127,253,169,254,177,243,177,62,219,236,244,134,183,245,206,217,203,181,131,217,193,249,225,217,78,103,181,115,243,43,220,135,128,198,105,125,181,209,169,223,29,245,58,103,107,225,193,172,243,190,30,220,116,14,7,171,239,58,199,245,151,128,210,73,125,43,234,28,158,189,218,234,116,26,159,1,158,205,250,16,238,255,18,174,2,37,62,212,135,135,222,65,29,218,187,109,156,118,58,27,245,163,217,254,230,17,192,183,51,11,95,118,206,26,199,2,218,127,121,182,217,233,14,118,78,58,157,233,159,235,179,131,159,15,111,161,254,168,247,182,115,240,110,245,112,184,255,91,125,22,1,126,47,235,157,253,139,213,191,126,236,188,63,184,109,116,248,208,175,119,254,124,81,63,252,120,184,122,116,134,253,191,140,58,31,6,245,195,206,97,253,240,14,224,29,174,195,72,108,158,214,135,251,141,250,112,214,57,252,235,111,240,254,9,208,11,224,223,255,181,179,58,251,251,251,206,127,254,253,231,223,127,254,253,47,255,7,114,46,243,239,115,4,127,86,79,103,157,206,219,223,142,147,167,199,95,26,157,159,70,157,206,187,209,142,122,18,224,159,83,186,220,159,225,223,58,252,111,188,65,255,198,29,20,249,135,209,23,227,217,249,201,108,1,40,251,239,253,211,236,147,240,253,225,236,231,147,79,89,93,112,120,248,185,191,8,155,63,31,26,117,15,62,111,226,207,79,135,89,20,223,28,96,157,30,94,110,203,39,244,206,95,20,16,168,147,126,57,25,118,120,39,133,243,228,39,208,90,31,62,98,59,155,89,96,246,111,206,146,235,179,45,160,193,225,248,175,240,222,206,13,208,233,228,22,224,60,24,172,194,187,191,213,65,220,158,213,145,70,131,85,248,243,174,62,84,247,160,109,160,190,95,191,81,245,15,239,47,224,126,107,220,83,237,117,90,42,80,134,106,214,98,232,153,192,181,161,122,49,20,37,195,182,104,176,181,203,35,93,65,95,56,95,254,62,21,225,61,5,185,228,101,13,227,90,107,20,143,203,68,180,116,19,50,46,28,139,187,184,254,133,223,114,249,212,106,15,166,62,217,78,44,154,78,48,66,23,93,83,100,236,26,204,182,16,192,170,84,31,48,30,20,138,120,26,250,22,24,91,220,59,151,37,22,88,255,51,215,239,7,179,23,47,252,169,231,61,107,181,228,173,99,214,154,247,120,220,27,85,226,170,106,226,217,218,124,158,116,233,139,217,197,72,140,197,73,192,251,162,15,93,37,37,49,220,220,242,144,197,173,31,42,214,243,110,236,191,35,19,223,170,98,172,177,98,141,212,157,29,181,98,39,20,96,16,246,68,197,154,220,89,182,101,85,119,173,117,48,137,173,103,45,241,226,133,190,140,95,188,16,244,183,34,90,177,13,109,46,242,229,114,61,216,162,10,181,87,92,127,50,141,47,101,40,51,2,107,108,26,89,87,43,213,52,0,123,65,129,231,138,213,23,112,27,220,91,197,34,237,163,68,243,106,213,94,107,180,90,252,53,249,209,199,232,171,129,111,95,9,170,77,190,186,58,71,164,197,19,72,7,173,72,196,201,139,177,189,213,104,84,109,222,106,204,127,112,134,34,254,243,249,135,211,74,194,43,4,199,12,199,64,198,67,39,110,125,3,248,3,24,205,214,196,198,193,145,221,198,78,140,195,17,65,15,8,1,221,212,208,58,7,162,10,140,237,29,113,24,203,244,61,160,14,189,201,91,43,96,79,182,247,184,50,40,159,91,172,7,206,119,212,178,122,35,224,58,33,141,123,138,119,145,73,106,177,105,232,181,86,86,99,68,236,160,239,175,90,109,11,110,144,190,171,214,94,157,3,243,66,115,214,110,224,240,201,68,248,253,10,175,206,225,191,93,236,43,97,83,197,160,173,69,124,187,235,14,42,249,202,138,169,16,175,150,201,165,18,239,93,107,234,247,5,120,168,162,143,44,3,115,51,24,200,202,192,55,48,55,193,57,18,192,220,195,138,117,128,104,129,139,34,75,89,28,48,128,31,47,137,91,208,180,190,52,151,56,144,87,120,28,135,48,44,64,31,203,46,118,125,13,4,1,110,22,241,133,59,22,193,52,78,137,92,125,48,134,2,99,120,192,14,136,105,197,162,169,195,154,73,215,115,123,77,108,84,237,252,164,170,206,191,124,68,249,80,49,199,59,174,88,40,95,160,45,184,183,122,158,219,187,129,185,227,44,24,46,219,128,70,113,74,37,30,185,145,130,164,186,27,63,9,34,80,38,67,65,89,2,8,75,226,9,57,184,65,203,130,81,111,89,251,122,246,176,202,161,24,240,169,23,87,173,86,171,37,94,127,167,5,168,166,134,95,142,10,16,31,101,73,142,89,96,208,139,3,213,18,11,70,175,21,228,48,252,252,233,68,177,7,226,15,165,241,18,156,17,20,199,15,57,191,32,204,51,250,96,89,90,124,201,147,162,84,79,100,154,94,118,29,238,203,130,101,184,167,123,120,98,217,6,103,100,24,245,130,144,150,193,214,156,29,103,195,120,86,251,46,125,44,88,226,43,93,222,251,135,59,43,91,214,131,43,208,42,126,159,123,129,47,140,26,223,27,187,204,106,222,151,5,139,121,223,100,60,132,195,238,69,240,46,242,42,220,22,118,88,125,224,245,214,250,214,150,45,228,79,72,63,82,124,219,177,221,107,189,231,241,200,1,182,85,213,237,145,122,226,250,250,137,223,170,244,86,71,213,250,58,138,241,94,171,53,170,130,170,111,53,118,133,23,9,146,65,221,86,175,54,218,141,102,46,153,23,45,191,237,108,189,238,214,43,235,53,120,92,109,194,21,190,110,247,170,15,61,30,9,198,155,81,171,34,106,97,181,222,93,173,136,189,240,245,118,179,81,221,237,134,130,223,236,82,5,129,21,194,26,199,10,235,102,65,136,5,188,38,176,96,115,30,213,91,219,115,105,201,60,140,154,145,29,53,99,219,107,250,134,77,243,233,237,126,28,188,59,255,89,83,98,13,228,22,15,135,83,144,166,113,228,120,194,31,198,35,50,67,184,51,180,67,248,219,5,213,205,157,176,170,201,83,32,78,175,64,156,81,43,174,245,128,68,96,70,180,226,215,141,230,168,30,219,221,86,92,71,34,107,138,40,196,123,0,126,195,196,7,41,1,132,88,29,253,152,208,193,70,172,126,28,229,201,1,212,88,93,255,113,84,82,138,52,1,146,172,110,38,165,89,154,248,246,109,179,59,159,47,203,69,63,100,181,93,63,232,17,181,148,110,34,149,4,202,169,57,112,193,60,43,170,162,31,164,40,7,194,9,7,237,161,106,98,16,214,255,246,183,250,208,182,234,150,241,200,249,241,111,245,58,89,137,32,187,67,119,56,20,32,123,177,101,57,3,44,251,50,190,2,129,107,155,96,0,226,253,251,156,70,150,208,72,16,205,215,147,90,194,142,181,113,164,32,116,38,48,57,129,9,192,248,36,123,82,218,157,208,6,88,28,125,104,17,233,2,106,200,109,197,187,60,97,20,78,56,185,164,5,148,5,244,249,244,248,226,250,172,243,169,243,254,188,245,0,92,241,222,13,69,63,106,174,109,109,216,192,53,234,110,227,101,3,239,246,41,40,232,139,40,106,2,115,204,237,207,199,215,23,157,253,243,214,229,67,204,135,77,43,230,221,218,204,29,184,0,119,232,130,161,229,221,55,173,95,240,126,110,167,21,64,73,3,152,70,141,115,122,96,86,241,192,98,50,42,156,28,29,102,138,105,253,219,172,240,137,30,152,85,198,127,143,99,179,198,251,143,23,23,153,10,20,15,165,117,130,200,172,119,97,60,158,95,33,126,111,142,143,78,14,19,12,121,31,40,116,61,141,68,136,214,165,249,102,7,75,88,90,130,11,37,77,235,179,186,103,96,237,50,208,227,100,229,185,62,24,41,56,134,108,38,186,19,244,125,108,180,14,155,224,11,132,80,14,119,188,107,16,83,131,45,251,158,128,33,60,11,194,12,129,206,146,103,178,87,125,255,61,122,29,5,81,156,199,245,93,242,76,246,119,46,188,65,13,230,4,152,59,162,207,244,27,104,138,69,240,6,67,61,52,4,231,46,30,177,195,131,119,103,224,177,130,135,9,94,192,82,253,227,205,53,58,73,110,239,218,205,242,13,61,100,199,103,172,211,239,135,192,147,9,56,73,1,151,5,172,2,190,209,173,96,93,144,24,55,8,22,12,19,59,124,119,112,86,253,22,24,174,125,17,143,121,116,83,14,203,169,46,148,176,168,91,221,41,17,33,169,252,77,189,171,60,130,242,222,223,202,194,60,69,12,82,40,64,120,196,84,67,108,54,194,117,160,20,42,230,226,2,131,112,123,238,0,231,225,210,32,142,131,190,200,206,252,55,46,123,79,15,37,20,23,225,61,244,141,188,248,150,97,101,230,14,216,125,48,93,9,5,27,241,91,124,14,88,118,93,207,141,239,217,36,12,186,158,24,71,186,127,153,237,114,173,86,100,192,178,165,251,168,249,0,224,236,91,54,192,240,214,178,125,160,55,192,84,14,99,79,92,79,92,223,4,240,224,136,213,217,217,79,23,140,158,171,169,3,147,24,212,238,209,249,217,206,250,246,54,146,74,206,162,149,131,163,21,86,193,171,211,79,111,214,55,79,26,107,140,150,240,7,160,6,170,12,43,64,67,170,198,202,217,201,218,218,246,203,250,201,197,206,171,70,99,197,168,184,144,154,81,70,6,246,34,191,0,235,249,233,114,96,158,159,174,44,217,11,176,131,136,243,253,124,58,58,63,90,142,32,84,115,217,190,64,162,231,123,2,169,158,239,71,241,38,54,143,165,50,52,194,212,18,29,171,52,90,112,201,129,45,250,213,93,230,139,33,173,238,2,117,111,193,124,199,69,49,119,232,115,143,85,66,129,25,76,40,120,106,235,212,22,174,228,5,28,196,33,52,186,236,16,76,120,239,6,168,3,66,77,240,56,202,10,91,44,97,73,137,226,237,145,96,254,116,220,21,208,29,120,249,46,174,210,97,10,7,213,98,159,222,48,217,96,132,18,145,156,212,238,212,235,70,11,129,9,51,26,45,11,204,245,68,132,215,94,16,76,22,67,197,160,10,147,85,148,24,74,64,211,53,180,112,118,113,238,227,164,244,4,27,6,14,99,239,64,197,67,85,74,16,137,216,88,112,31,38,43,76,209,120,4,246,197,112,4,150,134,141,25,17,204,67,105,50,6,95,218,141,65,192,65,3,206,146,216,160,163,161,112,185,134,89,1,158,111,70,183,92,92,156,105,178,233,82,137,195,123,236,107,226,185,61,57,238,178,16,121,51,75,30,26,114,165,98,48,69,0,179,167,80,45,117,239,209,127,102,212,126,231,236,216,97,159,15,233,2,163,166,208,166,231,221,195,91,61,1,77,3,203,77,101,63,66,15,155,205,162,64,146,65,247,18,141,130,169,7,173,138,116,74,96,211,75,170,242,105,28,0,188,192,224,97,140,195,233,6,25,125,222,129,226,154,42,102,186,88,18,1,139,48,13,66,3,44,235,32,98,50,245,145,9,152,13,247,6,43,98,76,50,166,37,99,1,2,221,21,125,64,28,230,88,131,32,214,243,105,201,73,1,213,123,152,199,115,127,77,201,151,6,196,135,186,132,201,18,101,253,0,133,241,30,153,13,227,126,160,103,84,175,186,178,154,20,129,239,48,21,153,33,206,68,124,34,52,33,232,109,34,48,12,159,206,46,150,152,194,152,108,238,236,188,122,165,241,129,215,20,58,203,141,1,154,136,215,96,158,1,32,121,75,145,233,199,18,141,195,0,131,43,40,228,13,61,10,164,165,170,221,48,184,1,103,158,125,32,133,68,163,34,73,125,15,243,138,192,39,157,95,17,119,124,60,241,64,87,140,239,241,61,245,90,15,19,37,118,118,54,23,130,76,134,108,6,228,56,0,118,5,51,48,6,165,226,23,32,167,82,150,148,106,123,144,110,137,248,105,173,200,24,22,28,128,35,9,97,19,158,1,149,163,122,83,210,249,218,237,39,151,8,100,189,73,142,6,60,118,216,185,16,236,211,81,231,240,253,17,181,61,152,134,49,202,142,190,136,185,235,45,150,110,69,164,166,147,62,204,182,39,112,147,149,30,71,17,80,154,76,187,128,213,136,25,239,68,14,59,83,172,22,143,64,176,112,154,200,52,217,97,234,134,193,152,5,10,112,197,89,152,22,51,201,191,65,162,155,106,147,25,173,38,220,204,245,60,156,136,192,187,40,76,85,135,32,24,200,160,129,87,190,130,12,168,241,158,162,2,213,249,154,113,54,105,162,95,118,216,47,210,234,147,139,21,210,43,142,100,177,77,211,111,48,5,180,110,124,204,245,148,47,201,224,181,122,129,144,6,217,167,218,5,42,106,231,34,7,216,242,28,80,226,83,201,17,132,2,150,247,169,152,118,48,192,187,97,210,114,200,76,220,165,187,45,115,167,168,165,201,34,159,42,233,244,155,251,236,121,152,225,121,45,205,27,57,218,133,238,15,168,14,25,229,96,2,93,200,58,18,146,131,192,247,133,90,100,147,197,96,108,68,28,199,239,137,97,1,237,126,129,55,174,223,243,166,125,168,127,242,203,5,177,122,215,133,137,11,165,143,206,231,197,250,189,136,98,136,111,100,120,247,44,195,129,6,196,32,28,101,109,54,240,248,48,241,88,6,76,248,164,155,236,226,43,121,36,169,17,100,78,34,157,209,90,2,242,66,247,193,138,195,169,176,154,214,145,175,20,161,53,224,94,132,79,14,181,110,156,47,64,52,114,81,92,94,23,135,52,99,183,103,198,241,189,198,193,116,139,142,97,28,169,41,114,138,108,153,158,71,26,144,232,28,177,149,158,28,113,209,95,161,209,90,33,5,154,60,42,208,3,6,18,218,148,131,6,212,145,173,98,86,22,227,221,96,42,173,5,180,153,129,2,182,161,210,108,38,98,96,17,221,156,98,146,254,242,52,60,39,44,76,18,42,16,22,146,112,20,140,197,53,76,44,23,227,213,241,181,97,95,132,98,224,222,101,99,14,99,209,209,53,229,64,167,70,199,153,170,158,240,14,216,45,182,196,68,114,17,249,96,195,144,242,71,37,187,100,218,91,137,100,139,169,101,162,3,111,156,188,81,152,69,160,217,131,25,24,37,168,49,224,33,143,164,129,223,69,195,43,166,145,96,220,180,205,150,155,44,100,25,95,39,14,34,41,216,66,100,43,117,32,153,44,151,104,174,59,155,236,237,187,223,24,181,65,163,236,129,25,130,204,35,197,185,156,248,210,199,38,73,174,157,109,63,136,149,31,14,182,189,118,103,159,61,57,204,62,214,108,90,244,99,217,210,185,133,121,109,250,186,230,64,103,141,126,204,168,188,21,215,18,95,96,222,129,59,204,204,147,14,149,51,137,239,129,46,87,134,63,218,221,178,1,166,94,37,191,36,146,22,57,98,235,11,143,141,130,201,68,146,186,20,15,96,137,24,167,83,243,97,44,29,9,209,124,214,152,167,232,1,46,159,222,238,255,98,217,107,48,107,15,46,44,123,189,105,189,153,198,59,175,108,12,194,175,210,163,13,170,99,217,64,134,55,159,47,26,235,13,203,222,130,218,60,2,103,9,216,111,27,28,173,147,183,139,137,16,14,214,55,193,116,158,161,255,6,118,186,103,18,128,200,202,206,176,144,157,200,66,165,120,232,17,213,39,161,236,171,1,123,114,188,222,31,159,2,237,80,10,159,124,248,5,252,237,96,102,217,239,142,223,190,131,185,4,6,158,101,191,239,252,5,202,249,221,19,240,74,11,241,90,81,185,8,242,137,180,32,15,116,185,132,250,151,145,219,27,233,161,137,114,14,64,34,202,49,53,3,29,103,201,82,79,224,67,88,16,62,239,143,15,241,170,159,193,231,113,44,52,36,69,248,207,209,11,62,72,138,23,129,79,206,178,9,56,34,146,0,15,34,247,51,205,168,129,192,209,74,94,4,87,64,244,35,48,10,233,253,104,161,44,125,138,57,191,21,119,53,120,37,97,12,53,108,185,48,198,177,223,11,5,143,100,46,130,180,20,240,30,101,29,160,202,199,193,20,132,175,10,112,32,114,112,39,187,32,220,129,34,202,104,70,215,128,220,62,211,47,75,171,38,222,30,198,26,55,22,27,22,25,135,77,26,199,3,111,26,141,164,196,188,229,94,62,10,10,118,43,150,179,180,92,137,16,215,119,199,211,113,198,47,246,0,28,1,242,164,143,198,122,60,195,108,120,122,89,5,34,201,78,70,43,34,26,149,99,3,242,150,223,147,66,118,199,148,88,31,11,144,189,19,84,172,81,156,107,97,73,7,219,112,2,66,252,227,185,99,183,176,142,161,154,198,10,76,85,248,42,36,77,191,8,43,97,36,74,181,89,233,27,78,56,230,1,125,133,201,215,23,96,92,248,160,195,136,46,5,160,117,49,83,197,75,129,44,73,156,184,51,18,72,13,58,237,189,211,186,238,27,33,207,132,142,174,49,196,21,199,96,211,193,133,136,70,129,215,95,24,98,99,186,46,51,234,38,246,57,110,100,140,64,33,205,212,124,72,162,70,92,5,210,240,77,180,211,206,204,168,32,217,37,20,86,163,233,165,199,11,179,62,208,9,245,229,148,164,192,28,171,128,133,107,146,170,42,173,157,30,199,0,106,174,83,105,166,36,221,50,220,192,7,125,191,151,81,189,108,187,212,10,76,114,141,221,116,2,53,205,208,204,122,163,49,254,166,184,101,74,93,64,22,215,216,110,193,178,90,130,190,153,218,95,77,225,108,52,211,36,79,145,46,32,165,113,54,211,254,198,1,143,144,187,50,108,213,176,217,152,223,17,191,74,98,173,53,26,240,172,161,37,66,180,152,233,30,163,203,88,206,129,197,164,72,42,148,96,63,160,4,52,194,0,229,86,143,163,225,47,101,182,212,78,185,192,175,72,227,26,25,220,54,150,133,93,6,127,148,44,198,45,97,25,173,242,150,162,3,114,158,234,210,100,141,16,172,100,240,222,72,179,202,50,35,136,170,189,13,116,230,203,230,58,140,203,167,163,115,116,238,162,9,104,68,33,195,188,169,232,210,208,151,129,87,62,245,165,99,112,157,24,237,180,126,117,45,243,29,136,0,134,102,161,135,20,71,9,197,173,27,160,203,141,235,87,82,2,69,224,218,73,207,162,78,251,146,152,218,64,157,160,254,6,158,161,105,249,139,12,250,179,138,52,190,149,85,137,113,69,52,38,119,94,85,237,228,85,21,116,234,127,153,130,42,145,173,166,221,224,27,180,141,150,225,54,90,17,98,129,154,185,18,124,189,214,11,16,78,38,97,48,9,93,114,160,201,15,28,243,27,201,25,82,112,202,80,151,122,13,183,163,22,176,132,249,255,75,231,211,233,241,233,219,166,20,20,3,33,59,132,75,244,36,0,228,9,128,133,26,145,4,216,10,129,187,146,160,242,181,62,120,209,5,127,196,188,17,125,57,108,180,0,41,125,131,252,26,19,141,84,127,138,76,205,176,26,211,213,228,224,36,85,104,25,212,8,164,147,245,195,58,189,30,10,228,51,220,176,171,234,113,55,38,251,40,80,45,33,45,40,203,65,225,169,129,50,24,79,250,192,101,48,15,164,131,92,6,51,1,68,16,203,74,170,71,159,18,67,158,0,126,196,163,226,91,58,178,78,109,250,160,93,130,240,230,107,129,14,136,223,114,243,35,11,134,81,101,41,18,71,83,162,49,6,28,239,89,56,165,125,161,95,11,150,148,105,165,48,37,11,68,209,50,240,160,153,142,163,75,107,72,24,32,198,155,228,253,111,1,10,216,114,234,103,64,123,131,22,33,235,73,91,186,0,221,105,126,21,17,224,67,136,105,126,147,49,41,225,214,98,156,43,23,120,104,144,173,32,195,77,248,148,216,191,78,83,96,74,150,160,180,125,158,86,82,11,81,184,91,212,48,59,74,149,18,204,251,251,172,33,135,209,212,212,160,49,218,212,238,2,202,72,242,230,135,80,56,245,80,171,165,169,56,182,204,236,69,225,227,161,55,188,216,97,136,179,249,59,111,63,125,248,124,118,125,126,209,185,56,186,254,233,232,215,243,214,165,165,180,133,206,187,183,173,110,146,211,4,55,202,45,183,70,83,170,147,136,92,184,33,177,6,191,114,228,173,27,225,221,186,201,243,107,148,196,216,24,8,120,197,27,22,10,198,41,40,220,107,253,166,24,12,104,238,90,201,194,10,92,235,197,148,244,177,140,241,88,193,40,121,113,36,238,212,245,149,13,172,112,253,254,195,225,17,226,242,97,48,128,210,115,12,76,201,36,89,184,123,3,134,75,122,71,101,93,15,19,103,100,137,190,246,232,48,3,184,250,224,67,163,159,15,207,174,207,62,125,184,248,112,240,225,228,250,231,163,79,231,199,31,78,161,131,45,123,251,202,62,60,122,211,249,124,114,113,157,214,73,170,180,182,236,36,187,212,86,65,177,243,228,1,109,221,133,225,105,61,91,179,189,128,227,180,58,87,110,46,62,34,213,14,55,100,50,28,247,205,71,29,108,10,30,96,178,166,101,61,163,220,122,28,5,71,167,22,201,84,184,153,232,158,7,200,63,45,95,204,216,47,250,174,98,205,48,143,213,90,45,188,182,106,53,119,214,172,234,110,242,162,19,248,202,165,111,165,153,118,213,7,76,245,87,192,235,125,35,194,193,0,234,46,38,207,231,14,205,176,170,206,4,109,43,76,186,219,131,43,220,123,128,219,14,232,178,58,159,211,30,140,56,120,39,238,50,125,168,45,48,141,59,107,85,56,113,112,78,156,92,89,219,174,194,205,231,9,204,181,3,160,102,165,58,151,68,17,154,74,102,19,5,10,54,210,225,112,96,198,252,140,70,106,5,32,39,190,58,238,211,142,0,85,25,30,15,229,21,61,197,120,116,82,243,2,24,176,90,54,62,161,24,160,175,67,79,200,219,70,248,210,54,51,192,253,80,89,121,174,122,96,114,191,11,18,80,158,59,209,178,86,86,197,234,10,165,171,211,102,1,213,14,66,81,104,132,36,181,231,62,245,250,80,196,7,211,16,51,34,15,21,186,45,35,197,82,82,27,196,77,24,137,99,63,174,164,116,26,106,58,85,51,141,20,80,74,218,64,22,208,136,57,42,42,73,8,2,35,32,140,21,139,128,132,161,183,49,19,179,227,247,229,148,144,76,109,180,7,92,246,44,71,100,157,132,250,144,14,68,51,133,137,6,169,106,235,225,108,22,81,134,82,5,90,179,128,10,18,41,110,125,232,126,193,204,108,60,83,199,21,81,37,63,105,29,101,148,97,22,169,7,198,109,102,151,135,34,192,181,227,70,71,127,159,226,94,161,203,181,43,135,66,226,212,199,25,15,249,56,178,5,102,150,230,166,114,195,142,85,14,106,187,241,186,208,105,194,171,241,101,227,170,218,44,148,211,214,166,74,181,32,31,230,115,91,14,192,231,208,107,21,50,121,75,201,19,183,74,8,99,243,86,158,202,82,244,180,90,162,138,222,213,204,122,143,134,56,157,132,161,141,133,227,67,11,43,37,236,160,14,100,74,184,0,252,19,184,142,38,158,11,18,201,134,75,189,234,86,225,213,223,127,175,196,173,70,213,54,118,8,181,146,29,66,197,30,229,154,43,118,168,164,70,93,229,238,69,32,229,64,170,193,95,78,127,227,121,113,142,154,132,201,177,219,239,191,167,91,188,18,66,2,57,204,41,8,150,69,223,19,212,210,103,146,68,21,28,95,115,170,100,103,109,102,158,168,185,171,166,73,113,130,24,178,173,117,237,104,79,188,98,246,143,219,5,127,112,112,255,65,229,97,26,122,77,3,206,85,235,53,157,215,240,193,255,56,21,32,22,200,141,176,199,34,30,5,125,240,161,63,95,88,54,157,69,128,248,57,210,84,112,7,247,21,185,119,8,15,79,162,249,101,129,143,36,147,138,192,129,147,91,217,148,69,218,124,146,14,64,136,100,67,34,247,68,24,195,197,92,109,156,66,75,242,64,250,64,139,112,83,120,89,245,232,62,162,141,81,15,9,240,31,206,191,21,250,185,222,185,165,120,228,156,150,167,63,5,179,150,153,76,110,115,57,77,220,150,181,23,135,109,96,229,85,188,234,183,45,27,174,86,246,72,162,169,211,214,180,192,137,46,175,146,157,120,230,145,93,22,203,136,229,122,123,197,166,214,234,186,185,69,13,211,254,168,167,27,141,159,108,180,239,222,234,54,186,177,175,50,225,105,201,83,237,30,130,231,202,237,108,175,236,66,55,21,196,221,111,53,118,253,189,82,219,71,9,171,93,127,117,85,210,41,106,149,214,187,244,175,236,160,197,91,173,232,247,223,163,86,235,17,91,233,197,139,103,229,61,25,98,97,151,144,161,61,111,6,58,12,81,146,134,52,15,239,87,86,43,193,107,75,45,135,129,143,108,85,129,58,146,56,154,184,114,27,176,244,148,245,129,121,114,185,151,136,141,17,15,180,77,241,172,143,150,21,128,13,201,178,186,53,130,22,153,236,167,55,18,96,39,245,101,63,86,155,89,171,145,26,6,130,178,109,169,157,26,76,62,132,113,104,151,143,144,36,127,30,171,62,134,32,208,211,26,7,183,162,166,79,72,83,9,21,9,82,250,173,228,16,24,150,30,7,35,95,197,45,70,110,194,33,178,47,13,131,1,78,29,57,125,78,198,104,98,137,102,247,97,168,141,75,242,167,134,201,131,40,195,233,78,30,255,5,210,177,212,34,125,241,194,216,45,91,215,203,57,150,157,51,43,11,118,112,195,86,26,249,70,220,71,80,169,100,91,108,186,239,99,229,185,110,152,153,91,136,229,12,1,107,200,118,51,214,19,215,74,124,229,114,161,221,148,236,13,105,55,94,188,168,40,166,193,61,70,106,31,33,57,35,160,175,36,39,116,131,187,98,225,235,78,24,242,123,48,10,232,183,34,112,203,203,107,252,91,196,5,137,64,250,163,233,202,122,77,185,33,133,174,113,159,140,200,153,248,113,203,50,206,20,165,157,159,73,141,93,189,165,70,110,181,86,27,177,125,126,219,229,97,173,11,142,96,95,111,28,5,161,12,180,87,22,47,248,90,215,202,194,0,140,203,109,13,153,204,23,193,96,231,236,165,98,27,37,35,150,192,46,192,156,1,219,66,128,153,4,67,99,26,117,28,75,18,67,142,99,5,109,184,241,203,245,171,249,110,1,46,222,239,75,168,42,15,184,179,167,25,219,52,166,240,155,55,192,154,46,16,178,240,190,178,11,52,102,207,214,170,184,117,92,155,252,128,16,82,35,90,68,6,179,94,41,194,209,98,64,209,245,65,181,37,225,21,184,241,200,240,83,138,112,97,111,197,48,174,49,11,228,203,138,249,75,2,190,192,223,192,214,153,89,107,209,90,96,105,187,146,53,202,34,137,139,186,44,141,58,62,210,105,105,219,101,221,202,136,221,114,221,170,192,225,210,221,170,182,115,221,38,177,186,39,59,77,163,122,203,116,153,182,155,235,80,6,124,158,236,77,197,243,150,233,74,181,56,151,214,12,153,227,25,61,82,211,217,38,122,23,57,109,214,83,117,116,42,202,139,23,133,71,229,210,75,31,33,144,55,174,42,138,205,209,129,177,105,194,11,152,199,36,211,138,177,15,52,209,112,214,170,221,58,42,221,165,232,193,208,86,125,222,173,77,251,19,173,28,1,13,240,97,158,173,97,36,66,122,157,224,111,57,82,11,30,160,154,172,88,116,60,169,37,55,247,17,137,77,93,97,218,114,87,43,248,238,152,79,12,20,83,187,240,7,48,72,228,14,200,93,173,227,163,83,126,90,113,171,175,193,121,1,197,69,21,96,182,103,187,181,241,240,142,42,201,32,55,223,185,182,247,254,217,29,251,216,113,198,55,191,44,152,65,165,48,196,134,247,18,231,189,21,242,9,159,65,21,109,63,70,173,75,180,254,26,187,193,158,214,162,187,1,24,140,209,101,112,213,186,228,240,215,118,241,143,15,127,174,118,83,99,63,49,14,18,115,159,198,241,9,167,164,204,25,120,200,241,44,158,7,50,71,15,100,130,94,73,209,198,1,14,206,113,35,186,128,223,31,46,233,34,34,139,107,215,187,16,249,200,193,161,89,254,154,134,4,25,95,115,170,85,133,57,149,30,82,167,35,20,118,49,152,198,104,199,238,20,52,204,110,6,255,202,67,170,188,72,255,152,160,117,164,162,92,18,188,165,195,39,161,232,79,123,34,199,91,114,70,150,70,77,52,171,131,37,4,232,34,251,24,193,56,155,39,49,60,184,84,134,2,72,152,185,253,80,196,53,111,160,40,140,229,217,126,101,177,49,83,23,163,24,81,218,91,111,51,206,76,130,71,52,119,53,59,222,24,110,50,251,44,132,191,74,44,148,167,123,127,202,172,169,22,71,86,2,34,161,58,66,81,145,153,14,226,181,193,108,53,183,159,156,56,82,148,47,37,245,204,131,166,181,126,17,213,106,179,188,201,50,41,173,99,32,24,68,81,72,60,22,201,82,33,192,184,245,68,100,148,241,149,228,52,21,0,70,66,96,235,144,12,30,1,228,5,64,155,24,12,102,125,164,51,144,87,91,203,100,72,99,197,52,166,149,17,148,232,42,153,195,179,56,212,37,170,175,117,213,104,4,90,18,73,35,111,51,196,72,226,67,35,23,241,67,225,65,161,218,159,165,188,110,149,152,214,0,17,6,94,234,149,191,245,87,171,127,115,204,159,74,173,226,252,88,173,190,174,107,5,242,48,230,95,130,176,137,19,207,30,187,62,93,174,95,73,33,9,151,27,87,54,46,120,99,79,112,183,133,5,160,167,154,151,84,159,106,82,29,44,186,130,153,4,218,8,147,252,138,176,165,83,220,4,30,77,95,55,251,36,78,52,27,119,168,175,182,43,127,231,182,12,51,29,160,179,245,38,8,101,164,169,132,35,80,215,1,23,208,15,207,201,46,121,122,22,122,164,48,220,61,201,55,53,165,249,18,38,117,212,131,85,139,85,208,169,130,102,93,238,199,171,86,85,105,82,58,222,10,91,240,16,130,164,1,230,32,175,227,81,164,208,148,200,152,71,201,97,62,151,89,238,160,186,232,7,101,31,99,98,2,88,41,60,97,16,124,128,71,82,164,60,162,230,211,92,67,36,244,209,96,177,60,198,40,15,154,90,211,75,13,61,187,88,75,207,85,201,142,210,72,218,229,173,236,160,86,192,167,228,195,107,52,26,236,132,84,213,215,22,212,209,153,243,140,223,130,69,141,233,9,207,172,166,245,171,204,172,86,249,172,99,240,80,105,249,216,143,117,117,71,206,62,13,68,52,29,143,121,120,175,65,229,18,16,183,21,59,48,31,112,65,116,113,248,93,30,108,5,195,208,23,119,31,208,182,86,67,87,125,214,170,173,161,145,98,56,244,216,229,192,13,199,51,30,226,201,91,254,141,165,200,172,206,7,114,81,181,118,195,96,6,166,242,53,10,1,84,123,116,120,20,242,121,142,181,205,227,136,114,231,47,129,249,189,91,194,109,246,19,35,100,196,118,244,129,208,172,60,200,67,66,94,69,121,170,143,81,242,241,65,151,226,197,78,76,30,218,15,1,246,78,33,224,11,232,98,64,129,163,242,64,207,105,26,10,178,44,245,155,250,176,28,62,113,245,105,70,120,76,14,158,129,16,213,35,183,31,140,234,34,154,224,142,233,235,177,75,251,233,174,161,14,148,123,148,77,91,151,224,149,245,140,33,239,150,40,244,172,37,131,17,128,206,47,89,10,162,46,205,251,69,39,204,201,177,215,65,61,219,250,112,138,75,28,242,189,175,58,127,14,125,116,90,145,214,242,56,57,177,71,61,119,66,93,195,25,38,87,93,92,105,73,78,180,121,188,230,110,30,139,116,45,30,49,145,103,40,97,192,78,46,29,89,246,90,163,241,35,248,138,106,149,72,156,161,72,23,179,3,108,14,15,59,254,49,118,70,84,39,118,34,245,235,41,231,52,93,193,215,46,8,150,103,10,106,198,41,41,78,114,72,74,181,94,201,60,215,199,165,44,168,157,71,201,200,222,90,128,147,171,32,76,115,20,36,132,126,203,124,246,35,126,119,160,158,131,36,61,170,165,208,175,76,114,40,239,209,199,153,95,164,96,97,237,32,166,37,172,53,58,42,16,46,121,107,171,33,205,134,194,199,5,212,121,131,15,233,183,14,168,197,166,53,2,110,161,229,43,155,86,204,255,100,211,42,214,159,170,180,130,129,199,124,159,235,4,130,82,199,152,150,225,65,129,152,105,6,232,20,23,29,226,236,225,225,25,219,46,123,242,184,148,29,209,132,251,212,136,20,40,231,180,195,90,195,98,17,108,240,228,107,129,107,60,9,156,34,86,25,112,18,238,82,224,130,137,1,27,137,190,204,7,63,18,77,135,43,118,62,114,155,56,84,6,223,27,140,127,45,88,20,90,180,164,226,246,181,137,185,104,117,5,156,111,238,232,77,12,175,211,176,177,218,235,164,151,48,153,25,246,142,75,130,168,92,175,187,196,151,252,106,153,133,17,208,14,230,242,199,202,170,143,80,26,0,235,96,57,221,148,44,130,36,22,52,199,10,245,54,195,149,16,99,165,163,106,167,139,28,22,234,59,99,228,147,243,186,112,89,48,123,238,40,76,224,52,198,158,243,35,113,51,241,145,246,37,201,128,6,159,177,97,111,52,170,213,71,227,5,180,182,249,141,126,185,211,15,124,65,235,148,210,86,21,40,5,176,91,60,119,177,58,199,57,108,126,96,200,210,107,5,37,214,63,230,137,86,10,90,229,89,67,31,45,133,129,42,211,60,53,172,119,60,128,232,47,53,221,16,208,31,176,132,166,240,52,125,120,35,174,87,214,126,212,133,244,101,130,74,21,173,104,58,185,140,100,8,137,116,174,242,12,178,194,222,173,154,235,202,149,7,144,72,164,65,119,181,120,50,63,228,130,174,77,128,7,12,192,132,200,174,59,227,148,229,14,238,229,35,56,40,173,65,214,157,78,242,53,215,116,81,230,172,205,92,25,78,250,108,33,158,199,149,237,128,68,168,148,202,86,34,158,229,211,144,207,106,18,47,28,18,74,222,45,218,222,15,152,227,97,174,213,252,144,57,153,82,45,216,232,135,46,8,153,166,30,55,48,111,97,180,155,52,23,18,11,92,134,225,196,101,182,25,218,141,93,189,2,3,201,36,116,2,127,242,1,169,184,148,123,50,131,163,234,54,179,190,129,122,106,209,41,101,146,38,180,66,190,168,73,99,173,125,233,38,181,140,206,183,134,65,1,226,108,74,28,161,44,72,12,43,40,25,251,218,84,76,224,206,102,116,65,69,55,157,17,193,53,242,181,75,193,206,180,85,42,188,181,67,140,133,37,71,172,62,199,175,73,169,56,55,210,198,126,2,141,71,195,227,139,66,219,22,157,131,172,113,83,81,135,101,9,135,209,7,23,157,31,243,208,58,152,205,229,1,128,164,94,170,5,147,162,66,160,196,233,226,73,119,84,255,17,18,57,229,171,203,118,137,60,75,130,34,113,152,132,107,176,229,36,99,192,109,53,118,221,189,87,160,142,86,171,73,140,36,13,160,104,10,22,142,47,38,93,73,149,19,37,227,210,178,61,252,24,39,20,83,172,166,12,133,76,63,64,124,198,173,178,248,103,102,102,225,59,185,57,144,66,96,201,197,214,194,104,161,180,218,149,22,166,217,126,49,145,13,79,233,165,131,188,139,25,129,50,35,6,222,154,207,243,150,167,10,143,90,87,118,18,222,93,73,132,153,95,206,95,126,49,234,215,74,227,107,42,200,151,172,210,67,41,72,128,16,119,186,52,81,128,227,174,237,163,241,36,190,151,60,131,207,2,24,163,15,254,155,160,55,141,240,86,86,254,224,239,131,171,133,247,192,159,248,45,172,7,9,107,51,235,3,39,107,42,123,104,136,37,206,107,238,11,42,150,57,248,237,199,19,24,96,194,107,207,86,50,2,54,12,78,238,2,181,148,68,186,75,135,174,100,74,170,23,10,161,88,169,120,10,156,95,248,222,139,85,93,200,40,114,129,199,180,20,11,47,183,165,185,180,146,46,229,232,57,98,17,5,219,148,253,42,238,40,99,86,62,128,102,211,115,186,109,23,220,145,192,151,131,215,233,247,115,195,17,23,226,232,232,150,20,30,234,165,247,111,200,153,180,31,201,196,156,151,71,155,231,217,5,139,52,98,110,176,45,46,107,148,115,108,20,132,49,89,230,77,21,245,46,229,225,255,125,76,123,220,255,183,224,88,181,4,36,23,170,118,213,111,43,201,75,230,230,2,139,20,231,106,65,132,195,219,118,38,203,226,24,192,173,168,22,74,22,95,36,139,188,161,56,98,179,116,52,84,4,253,255,85,26,119,151,188,54,232,212,222,52,106,175,174,30,214,236,205,249,239,151,234,114,107,94,253,161,94,125,93,73,32,132,174,26,123,24,137,21,123,173,237,173,173,141,173,215,149,204,234,10,102,112,160,11,208,204,61,150,249,172,93,129,103,78,208,97,28,34,76,54,132,52,238,26,248,249,70,220,137,214,184,123,3,255,44,28,174,234,247,104,99,110,38,155,180,146,171,204,12,149,71,37,131,131,57,77,188,75,159,223,130,191,120,91,139,121,55,146,78,36,109,212,190,192,91,240,113,131,150,54,75,118,213,17,184,229,73,49,228,181,38,51,105,101,53,64,165,159,78,179,21,100,37,62,44,120,211,208,43,218,6,194,209,251,113,76,35,1,59,71,103,84,53,110,52,87,72,21,40,105,245,243,225,89,210,212,10,182,1,45,79,193,187,149,205,25,19,3,27,83,30,102,6,99,134,155,94,158,68,58,215,16,76,19,60,176,15,20,187,164,129,118,203,21,246,178,125,43,61,110,183,52,11,14,28,105,12,203,119,49,98,9,239,165,223,138,48,58,75,63,24,139,137,158,28,209,35,119,221,230,105,0,1,234,80,206,92,210,249,106,156,33,180,242,247,237,216,193,173,77,152,35,150,195,40,253,18,162,162,48,94,214,80,38,200,118,241,150,6,90,73,18,155,167,113,3,187,44,97,169,133,159,202,0,13,243,90,118,37,25,51,43,167,165,207,202,204,196,68,182,48,1,138,233,248,11,16,54,191,5,170,116,204,8,64,169,59,218,20,146,219,171,235,187,185,6,95,118,13,210,206,216,0,247,15,1,110,14,65,186,173,233,59,192,135,247,185,205,166,9,160,165,65,48,185,220,3,3,174,115,11,48,3,84,231,71,60,204,171,205,108,102,45,157,172,93,158,179,156,199,12,211,150,205,209,135,201,193,231,114,242,38,145,164,106,233,220,43,157,50,133,25,46,231,112,209,171,139,106,244,153,70,102,124,173,209,240,104,212,202,176,9,69,230,154,188,99,29,117,74,183,55,69,213,124,73,52,237,142,221,184,56,75,75,253,206,98,38,147,51,226,81,206,203,171,22,243,162,48,0,161,143,233,231,173,60,4,34,116,193,61,248,77,200,228,211,234,46,157,126,191,56,249,66,92,202,245,179,171,100,5,54,151,190,202,171,175,185,51,153,70,163,68,181,54,147,119,90,151,160,133,229,211,43,227,169,122,68,249,24,153,195,102,154,151,87,200,158,173,31,28,224,24,164,224,67,113,178,98,29,27,212,190,168,228,115,75,192,227,54,182,82,104,156,229,192,82,216,10,126,43,22,6,8,44,101,221,148,120,247,200,158,37,3,149,154,1,101,244,46,51,159,22,242,216,66,80,140,47,198,46,92,43,134,106,123,46,217,145,229,145,111,195,230,164,3,93,105,197,207,29,162,175,29,7,1,10,185,202,3,29,197,143,121,192,77,11,195,228,54,101,3,231,60,223,68,66,91,114,251,4,119,65,12,52,165,175,61,71,183,91,69,29,164,21,167,35,89,207,213,241,3,153,176,83,233,10,125,53,147,84,94,41,9,86,168,8,197,31,251,211,4,25,48,114,30,118,17,158,66,50,78,186,151,14,96,92,148,27,117,9,115,47,126,241,34,217,250,70,237,191,120,145,217,230,88,226,195,253,113,191,162,144,126,151,2,173,198,212,128,236,98,24,69,102,163,171,51,170,193,36,48,93,15,205,135,217,199,234,21,249,25,121,40,82,59,39,164,234,145,55,86,174,174,218,238,155,53,247,122,129,231,241,73,148,60,230,33,12,79,43,73,144,79,138,219,89,175,48,172,225,249,131,86,91,46,244,34,2,238,144,150,21,148,183,195,50,213,105,102,66,115,86,251,187,20,39,123,55,24,88,181,89,28,101,66,191,50,117,235,86,219,216,22,32,13,90,218,123,146,33,175,68,144,21,17,46,216,249,88,14,63,86,59,107,80,39,122,38,75,89,41,246,178,100,205,203,231,182,150,5,137,181,157,107,154,226,187,210,179,160,203,39,60,110,90,28,36,65,41,73,216,206,46,75,38,244,75,59,211,173,37,225,73,163,119,250,148,132,149,175,81,206,71,201,251,12,44,28,131,5,49,235,164,6,10,124,18,76,166,147,150,60,195,67,62,20,119,0,75,95,0,106,242,32,143,182,252,54,70,102,232,123,48,237,98,99,220,185,57,42,9,64,248,205,176,252,160,16,236,53,249,133,230,165,70,38,243,130,30,158,142,188,205,16,76,226,23,9,16,9,28,207,29,79,192,113,111,93,57,23,139,227,72,171,39,106,93,70,121,138,166,210,88,2,60,93,93,1,70,138,133,14,183,81,170,101,1,3,37,93,46,219,67,45,73,4,82,61,201,246,217,27,245,120,65,63,184,108,95,216,76,87,218,141,172,89,203,79,132,125,122,156,182,142,238,230,66,30,149,86,46,125,250,45,195,183,233,99,153,202,88,248,50,224,146,60,220,166,111,161,237,117,11,108,216,77,120,208,232,10,63,85,184,20,79,62,245,129,194,118,201,23,232,202,40,34,175,228,46,58,249,23,164,210,2,165,65,128,38,30,186,89,7,119,15,83,105,154,130,170,148,113,13,139,242,82,178,22,141,107,27,136,81,234,29,103,53,127,121,91,86,91,134,155,216,41,24,193,218,107,214,46,96,250,70,210,8,153,37,120,78,154,128,14,14,40,56,37,15,82,117,28,135,4,129,244,223,50,232,103,47,77,252,150,70,226,184,159,135,95,114,144,134,254,184,159,21,76,70,66,111,42,157,22,33,135,141,103,240,58,162,253,218,163,105,23,119,107,23,144,42,130,188,153,69,196,204,185,165,110,50,59,203,37,79,19,110,189,94,108,135,195,238,12,255,92,227,205,96,26,55,118,94,209,207,171,53,187,39,79,36,181,125,111,152,165,137,138,116,91,109,178,172,18,196,22,39,123,232,23,22,164,123,148,231,100,168,19,102,244,38,213,246,226,125,169,122,65,232,169,77,169,107,48,195,228,58,117,43,73,52,104,179,181,4,129,199,192,248,30,253,175,67,111,235,255,178,222,128,145,217,198,191,172,55,224,65,182,185,84,111,44,195,159,41,55,74,230,251,30,176,108,1,44,91,127,16,88,182,1,150,237,63,8,44,47,1,150,151,127,16,88,118,0,150,157,127,25,119,54,160,183,142,231,37,253,101,180,227,35,82,213,16,122,20,170,108,127,18,227,0,84,14,174,228,149,201,61,195,220,88,176,87,93,209,183,96,105,100,61,179,5,118,135,132,167,141,1,129,84,157,60,98,15,43,63,104,161,81,76,194,89,34,134,118,148,73,49,212,11,217,197,60,60,124,48,99,233,154,213,65,123,100,107,31,28,92,44,172,172,212,77,98,239,36,18,62,219,219,234,19,109,20,94,88,88,57,97,91,163,190,60,45,145,213,217,254,206,163,239,189,90,43,190,247,106,13,223,91,127,244,189,245,70,241,189,245,198,98,2,170,227,191,179,68,148,15,23,190,36,53,179,241,194,233,201,219,202,169,152,142,248,52,42,152,134,143,177,252,34,99,104,109,253,17,211,34,21,11,25,35,2,126,77,67,130,232,176,108,87,163,173,246,187,41,240,54,252,126,45,168,219,185,24,68,154,163,183,176,64,37,239,149,135,21,138,41,200,233,188,82,63,5,138,46,0,121,49,213,12,171,235,235,168,116,158,36,178,127,51,177,164,80,213,17,27,74,18,100,70,122,32,43,100,204,75,208,101,77,252,200,49,138,213,236,51,126,7,70,86,35,247,84,27,95,141,134,245,109,116,82,76,245,164,133,250,21,228,163,28,79,118,145,166,206,127,51,21,141,167,116,154,106,141,18,253,19,198,91,142,200,102,14,255,63,135,202,95,55,227,129,22,105,230,255,55,145,134,154,89,14,121,185,145,224,123,163,253,85,204,32,207,152,253,118,68,83,253,154,100,173,166,190,141,155,181,95,146,180,90,150,217,88,147,244,99,208,39,187,240,174,12,133,162,7,35,133,124,249,60,98,174,239,129,163,191,80,88,231,5,53,182,244,88,172,56,111,199,152,89,186,178,15,245,132,114,29,174,105,74,88,237,95,240,39,53,71,164,82,34,10,47,236,15,45,19,104,244,157,64,54,44,116,143,158,245,99,125,251,180,89,74,90,54,167,120,157,235,124,89,52,213,198,170,199,186,154,112,55,124,58,238,58,141,84,220,245,12,170,127,35,48,234,156,163,71,96,153,250,203,64,99,158,118,196,62,211,43,249,177,65,131,97,2,191,147,199,121,251,107,120,46,203,99,198,155,72,28,156,241,240,87,134,12,190,142,3,241,90,157,79,254,216,40,169,195,168,21,79,100,52,125,25,141,8,158,178,21,5,243,69,90,35,180,148,57,174,76,136,127,28,116,70,167,230,224,151,136,242,76,45,238,226,101,225,215,28,151,115,4,76,249,165,123,201,41,138,116,110,254,35,18,165,56,204,255,100,215,8,7,225,241,197,129,39,156,33,150,77,195,206,90,205,223,70,148,178,224,218,127,19,255,203,99,233,241,59,50,215,10,189,239,57,3,206,177,225,239,56,5,30,129,158,232,243,175,224,254,130,211,132,111,83,48,179,52,127,193,96,10,238,81,202,141,94,234,234,187,220,11,134,5,105,201,189,218,226,146,210,136,188,44,90,106,73,87,110,22,145,84,4,247,101,236,38,239,91,237,23,116,34,248,110,74,150,209,122,182,7,53,168,250,43,224,114,11,7,90,71,235,229,147,64,167,6,61,105,47,49,211,102,194,156,146,18,122,202,92,147,246,94,76,95,199,73,83,153,16,162,189,24,145,111,227,81,147,112,153,196,222,15,247,234,112,135,79,240,83,177,103,65,24,39,15,206,194,0,227,66,30,83,91,242,147,130,116,101,56,175,234,53,56,184,39,134,88,17,97,204,109,144,89,90,221,75,31,28,251,195,83,3,241,74,34,128,244,42,67,94,111,163,193,170,88,7,127,17,119,248,69,186,60,229,115,166,235,29,47,252,110,52,217,205,113,110,110,81,237,223,143,101,211,229,242,165,120,181,72,165,101,140,125,98,92,185,16,76,139,118,38,101,115,177,74,153,48,181,200,170,76,54,139,158,203,106,95,59,200,73,248,12,207,140,101,244,183,54,227,33,29,128,32,239,232,96,91,181,28,154,217,18,182,212,80,20,94,83,123,208,74,134,99,179,125,33,43,50,117,174,57,171,208,199,136,48,145,90,127,34,183,10,163,178,105,48,99,238,0,244,69,72,166,139,225,249,181,231,127,63,254,45,44,166,127,149,200,45,225,3,139,204,248,110,187,227,97,174,36,139,241,179,45,156,37,17,195,186,145,155,162,206,237,72,121,217,161,29,192,109,185,32,143,95,146,184,15,166,152,130,155,102,164,176,174,24,224,215,22,166,147,97,72,7,93,57,12,215,192,207,131,177,144,95,157,144,5,248,201,36,249,125,45,249,225,9,185,79,55,178,213,87,124,240,107,67,189,32,12,167,19,249,81,81,202,185,162,141,154,14,59,30,200,15,54,140,40,167,14,94,33,189,45,219,177,129,179,192,85,70,160,213,123,146,106,182,226,186,40,150,159,166,18,108,1,10,14,249,55,203,76,39,34,227,161,162,80,210,17,235,186,62,199,44,75,253,57,103,145,82,86,31,237,97,28,235,241,244,129,30,160,115,221,248,221,180,203,244,3,134,27,156,145,210,14,75,51,58,56,243,141,3,100,186,247,140,50,10,233,115,35,242,224,24,171,144,253,97,49,201,120,18,99,226,136,247,200,10,209,84,83,8,49,185,215,159,246,148,68,165,79,221,112,242,125,39,244,13,24,108,144,8,216,13,120,216,127,134,67,157,176,170,252,106,143,235,27,223,241,73,78,153,237,209,231,153,84,46,40,163,67,64,74,70,22,200,70,220,65,224,96,7,178,201,207,231,251,230,56,101,132,111,93,143,132,197,228,158,118,60,28,16,179,45,132,223,147,115,84,166,176,243,48,38,201,90,195,201,153,157,51,102,186,94,110,25,202,40,82,74,223,52,59,181,44,159,132,46,157,28,211,222,167,3,112,88,70,254,83,38,161,138,243,200,107,14,146,127,130,9,116,93,76,157,162,12,15,20,87,20,96,110,250,129,47,138,249,2,75,38,141,99,42,35,38,221,129,246,82,87,223,134,144,86,78,32,140,136,219,147,17,46,213,108,75,97,160,68,186,169,220,10,226,108,0,108,241,164,140,205,175,12,150,75,219,3,148,196,70,68,227,17,13,106,102,90,253,123,43,149,101,117,9,82,36,127,42,146,126,111,20,146,170,87,219,23,83,155,218,84,235,249,163,194,242,212,206,30,169,100,81,131,39,244,172,216,158,142,28,203,8,233,227,45,233,100,27,201,114,73,83,197,37,218,228,228,49,73,85,184,66,255,66,30,211,149,244,33,95,251,36,197,48,59,36,250,45,215,84,242,253,236,107,30,47,104,238,52,160,132,60,213,222,36,20,143,181,167,134,134,62,4,35,51,153,248,130,234,120,128,70,75,30,201,101,188,143,155,52,240,44,46,171,253,179,11,106,3,24,77,234,152,108,186,107,105,171,72,228,236,185,95,169,14,204,230,251,61,109,163,254,119,79,242,242,180,194,127,191,201,46,243,36,217,11,246,73,217,63,95,235,18,237,141,54,146,121,39,72,207,230,154,54,26,220,104,127,141,37,185,88,115,230,27,206,114,230,66,128,74,80,220,200,91,8,41,88,255,227,44,4,73,180,255,9,38,194,119,181,12,254,112,162,163,44,243,251,223,79,112,200,236,250,36,161,253,105,97,145,134,209,37,105,114,75,158,143,126,170,131,152,104,204,140,227,120,114,1,95,244,222,96,78,202,57,206,195,71,150,239,190,177,3,242,35,51,71,239,3,91,160,107,137,223,224,100,114,15,91,217,162,216,31,134,59,235,42,60,136,250,189,253,255,1,173,192,210,71,116,183,0,0}; \ No newline at end of file diff --git a/lib/Helpers/bitstreamConvert.h b/lib/Helpers/bitstreamConvert.h new file mode 100644 index 00000000..59fff657 --- /dev/null +++ b/lib/Helpers/bitstreamConvert.h @@ -0,0 +1,70 @@ +#include + +#ifndef _BITSTREAMCONVERT_H +#define _BITSTREAMCONVERT_H + +class BitstreamConvert { + public: + uint8_t sizeOut = 0; + + BitstreamConvert(uint8_t sourceSize, uint8_t destSize){ + src_bitlength = sourceSize; + dst_bitlength = destSize; + mask = (1 << dst_bitlength) -1; + mask <<= 32 -dst_bitlength; + } + + bool convert(uint16_t input[], uint8_t size){ + #ifdef DEBUG_PRINTF + printf("converting: %d values %d-bit values\n", size, src_bitlength); + #endif + for(uint8_t i = 0; i < size; i++){ + push(input[i]); + } + return true; + } + + bool convert(uint8_t input[], uint8_t size){ + #ifdef DEBUG_PRINTF + printf("converting: %d %d-bit values\n", size, src_bitlength); + #endif + for(uint8_t i = 0; i < size; i++){ + push(input[i]); + } + return true; + } + + + uint16_t * get(){ + #ifdef DEBUG_PRINTF + printf("get %d %d-bit values\n", sizeOut, dst_bitlength); + #endif + return output; + }; + + private: + uint16_t output[32]; + uint8_t bufferPos = 0; + uint32_t buffer = 0x00000000; + + uint8_t src_bitlength; + uint8_t dst_bitlength; + uint32_t mask; + uint32_t outmask; + + void push(uint16_t data){ + bufferPos += src_bitlength; + + buffer |= data << (32 -bufferPos); + + while(bufferPos >= dst_bitlength){ + uint32_t outbyte = (buffer & mask) >> (32 -dst_bitlength); + output[sizeOut++] = outbyte; + buffer <<= dst_bitlength; + bufferPos -= dst_bitlength; + } + } +}; + + +#endif \ No newline at end of file diff --git a/lib/MiLight/CasaluxPacketFormatter.cpp b/lib/MiLight/CasaluxPacketFormatter.cpp new file mode 100644 index 00000000..2ac89284 --- /dev/null +++ b/lib/MiLight/CasaluxPacketFormatter.cpp @@ -0,0 +1,198 @@ +#include +#include + +bool CasaluxPacketFormatter::canHandle(const uint8_t *packet, const size_t len) { + return len == packetLength && packet[1] == 0x01; +} + +void CasaluxPacketFormatter::initializePacket(uint8_t* packet) { + size_t packetPtr = 0; + + // Byte 0: Packet length = 10 bytes + + // Byte 1: Bulb command, filled in later + packet[packetPtr++] = 0; + + // Byte 2: Casalux protocol + packet[packetPtr++] = 0x01; + + // Byte 3: 11 + packet[packetPtr++] = 0x11; + + // Byte 4 and 5: Device ID + packet[packetPtr++] = deviceId >> 8; + packet[packetPtr++] = deviceId & 0xFF; + + // Byte 6: Zone + packet[packetPtr++] = groupToGroupId(groupId); + + // Byte 7: Zero + packet[packetPtr++] = 0; + + // Byte 8: Packet sequence number 0..255 + packet[packetPtr++] = ++sequenceNum; + + // Byte 9 +10: Checksum over previous bytes, including packet length = 7 + // The checksum will be calculated when setting the command field + packet[packetPtr++] = 0; + packet[packetPtr++] = 0; + + // Byte 11: CRC LSB + // Byte 12: CRC MSB +} + +void CasaluxPacketFormatter::finalizePacket(uint8_t* packet) { + uint16_t checksum; + + // Calculate checksum over packet length .. sequenceNum + checksum = packetLength; // Packet length is not part of packet + for (uint8_t i = 0; i < packetLength; i++) { + checksum += currentPacket[i]; + } + // Store the checksum in the 9th, 10th bytes + currentPacket[8] = checksum >> 8; + currentPacket[9] = checksum & 0x00FF; +} + +void CasaluxPacketFormatter::updateBrightness(uint8_t value) { + const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_CASALUX); + int8_t knownValue = (state != NULL && state->isSetBrightness()) ? state->getBrightness() : -1; + + Serial.printf("Brightness %d\n", knownValue); + + valueByStepFunction( + &PacketFormatter::increaseBrightness, + &PacketFormatter::decreaseBrightness, + 10, + value, + knownValue + ); +} + +void CasaluxPacketFormatter::updateTemperature(uint8_t value) { + const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_CASALUX); + int8_t knownValue = (state != NULL && state->isSetKelvin()) ? state->getKelvin() : -1; + + Serial.printf("Temp %d\n", knownValue); + + valueByStepFunction( + &PacketFormatter::increaseTemperature, + &PacketFormatter::decreaseTemperature, + 10, + value, + knownValue + ); +} + +void CasaluxPacketFormatter::command(uint8_t command, uint8_t arg) { + pushPacket(); + currentPacket[0] = command; + currentPacket[5] = groupToGroupId(arg); +} + +void CasaluxPacketFormatter::updateStatus(MiLightStatus status, uint8_t groupId) { + if(status == ON) command(0x6F, groupId); + else command(0x60, groupId); +} + + +BulbId CasaluxPacketFormatter::parsePacket(const uint8_t* packet, JsonObject result) { + uint8_t command = packet[0]; + + uint8_t onOffGroup = groupIdToGroup(packet[5]); + + BulbId bulbId( + (packet[3] << 8) | packet[4], + onOffGroup, + REMOTE_TYPE_CASALUX + ); + + sequenceNum = packet[7]; + + switch(command){ + case 0x65: + result[GroupStateFieldNames::COMMAND] = "brightness_down"; + break; + + case 0x66: + result[GroupStateFieldNames::COMMAND] = "brightness_up"; + break; + + case 0x6A: + result[GroupStateFieldNames::COMMAND] = MiLightCommandNames::TEMPERATURE_DOWN; + break; + + case 0x69: + result[GroupStateFieldNames::COMMAND] = MiLightCommandNames::TEMPERATURE_UP; + break; + + default: + if(onOffGroup < 255) { + result[GroupStateFieldNames::STATE] = command == 0x6F ? "ON" : "OFF"; + } + + result["button_id"] = command; + break; + } + + return bulbId; +} + +void CasaluxPacketFormatter::increaseTemperature() { + command(0x69, 0); +} + +void CasaluxPacketFormatter::decreaseTemperature() { + command(0x6A, 0); +} + +void CasaluxPacketFormatter::increaseBrightness() { + command(0x66, 0); +} + +void CasaluxPacketFormatter::decreaseBrightness() { + command(0x65, 0); +} + + +uint8_t CasaluxPacketFormatter::groupToGroupId(uint8_t group){ + switch(group) { + case 1: + return 0xD1; + case 2: + return 0xD2; + case 3: + return 0xD4; + case 4: + return 0xD8; + default: + return 0xDF; + } +} + +uint8_t CasaluxPacketFormatter::groupIdToGroup(uint8_t groupId){ + switch(groupId) { + case 0xD1: + return 1; + case 0xD2: + return 2; + case 0xD4: + return 3; + case 0xD8: + return 4; + default: + return 255; + } +} + + +void CasaluxPacketFormatter::format(uint8_t const* packet, char* buffer) { + buffer += sprintf_P(buffer, PSTR("CMD : %02X\n"), packet[0]) ; + buffer += sprintf_P(buffer, PSTR("Byte 2 (01) : %02X\n"), packet[1]); + buffer += sprintf_P(buffer, PSTR("Byte 3 (11) : %02X\n"), packet[2]); + buffer += sprintf_P(buffer, PSTR("Device ID : %02X%02X\n"), packet[3], packet[4]); + buffer += sprintf_P(buffer, PSTR("Group : %02X\n"), packet[5]); + buffer += sprintf_P(buffer, PSTR("Byte 5(00) : %02X\n"), packet[6]); + buffer += sprintf_P(buffer, PSTR("Sequence Num. : %02X\n"), packet[7]); + buffer += sprintf_P(buffer, PSTR("Payload Chksum: %02X%02X\n"), packet[8], packet[9]); +} diff --git a/lib/MiLight/CasaluxPacketFormatter.h b/lib/MiLight/CasaluxPacketFormatter.h new file mode 100644 index 00000000..be0497f5 --- /dev/null +++ b/lib/MiLight/CasaluxPacketFormatter.h @@ -0,0 +1,30 @@ +#include + +#ifndef _CASALUX_PACKET_FORMATTER_H +#define _CASALUX_PACKET_FORMATTER_H + +class CasaluxPacketFormatter : public PacketFormatter { +public: + CasaluxPacketFormatter() + : PacketFormatter(REMOTE_TYPE_CASALUX, 10, 20) + { } + + virtual bool canHandle(const uint8_t* packet, const size_t len); + + virtual void command(uint8_t command, uint8_t arg); + virtual void updateStatus(MiLightStatus status, uint8_t groupId); + virtual void updateTemperature(uint8_t value); + virtual void increaseTemperature(); + virtual void decreaseTemperature(); + virtual void updateBrightness(uint8_t value); + virtual void increaseBrightness(); + virtual void decreaseBrightness(); + virtual void format(uint8_t const* packet, char* buffer); + virtual void initializePacket(uint8_t* packet); + virtual void finalizePacket(uint8_t* packet); + virtual BulbId parsePacket(const uint8_t* packet, JsonObject result); + static uint8_t groupToGroupId(uint8_t group); + static uint8_t groupIdToGroup(uint8_t groupId); +}; + +#endif \ No newline at end of file diff --git a/lib/MiLight/CctPacketFormatter.cpp b/lib/MiLight/CctPacketFormatter.cpp index 519841a9..af7a8061 100644 --- a/lib/MiLight/CctPacketFormatter.cpp +++ b/lib/MiLight/CctPacketFormatter.cpp @@ -50,26 +50,26 @@ void CctPacketFormatter::finalizePacket(uint8_t* packet) { void CctPacketFormatter::updateBrightness(uint8_t value) { const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_CCT); - int8_t knownValue = (state != NULL && state->isSetBrightness()) ? state->getBrightness() / CCT_INTERVALS : -1; + int8_t knownValue = (state != NULL && state->isSetBrightness()) ? state->getBrightness() : -1; valueByStepFunction( &PacketFormatter::increaseBrightness, &PacketFormatter::decreaseBrightness, CCT_INTERVALS, - value / CCT_INTERVALS, + value, knownValue ); } void CctPacketFormatter::updateTemperature(uint8_t value) { const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_CCT); - int8_t knownValue = (state != NULL && state->isSetKelvin()) ? state->getKelvin() / CCT_INTERVALS : -1; + int8_t knownValue = (state != NULL && state->isSetKelvin()) ? state->getKelvin() : -1; valueByStepFunction( &PacketFormatter::increaseTemperature, &PacketFormatter::decreaseTemperature, CCT_INTERVALS, - value / CCT_INTERVALS, + value, knownValue ); } diff --git a/lib/MiLight/FUT020PacketFormatter.cpp b/lib/MiLight/FUT020PacketFormatter.cpp index bca30b28..aa1fbef7 100644 --- a/lib/MiLight/FUT020PacketFormatter.cpp +++ b/lib/MiLight/FUT020PacketFormatter.cpp @@ -23,14 +23,14 @@ void FUT020PacketFormatter::nextMode() { void FUT020PacketFormatter::updateBrightness(uint8_t value) { const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_FUT020); int8_t knownValue = (state != NULL && state->isSetBrightness()) - ? state->getBrightness() / FUT02xPacketFormatter::NUM_BRIGHTNESS_INTERVALS + ? state->getBrightness() : -1; valueByStepFunction( &PacketFormatter::increaseBrightness, &PacketFormatter::decreaseBrightness, FUT02xPacketFormatter::NUM_BRIGHTNESS_INTERVALS, - value / FUT02xPacketFormatter::NUM_BRIGHTNESS_INTERVALS, + value, knownValue ); } diff --git a/lib/MiLight/MiLightRemoteConfig.cpp b/lib/MiLight/MiLightRemoteConfig.cpp index 7db763b3..d7ba57d4 100644 --- a/lib/MiLight/MiLightRemoteConfig.cpp +++ b/lib/MiLight/MiLightRemoteConfig.cpp @@ -11,7 +11,9 @@ const MiLightRemoteConfig* MiLightRemoteConfig::ALL_REMOTES[] = { &FUT098Config, // rgb &FUT089Config, // 8-group rgb+cct (b8, fut089) &FUT091Config, - &FUT020Config + &FUT020Config, + &CasaluxConfig, + &NLGConfig }; const size_t MiLightRemoteConfig::NUM_REMOTES = size(ALL_REMOTES); @@ -105,4 +107,20 @@ const MiLightRemoteConfig FUT020Config( REMOTE_TYPE_FUT020, "fut020", 0 +); + +const MiLightRemoteConfig CasaluxConfig( + new CasaluxPacketFormatter(), + MiLightRadioConfig::ALL_CONFIGS[5], + REMOTE_TYPE_CASALUX, + "casalux", + 4 +); + +const MiLightRemoteConfig NLGConfig( + new NLGPacketFormatter(), + MiLightRadioConfig::ALL_CONFIGS[6], + REMOTE_TYPE_NLG, + "nlg", + 4 ); \ No newline at end of file diff --git a/lib/MiLight/MiLightRemoteConfig.h b/lib/MiLight/MiLightRemoteConfig.h index 966bf16a..cac20155 100644 --- a/lib/MiLight/MiLightRemoteConfig.h +++ b/lib/MiLight/MiLightRemoteConfig.h @@ -8,7 +8,8 @@ #include #include #include -#include +#include +#include #ifndef _MILIGHT_REMOTE_CONFIG_H #define _MILIGHT_REMOTE_CONFIG_H @@ -49,5 +50,7 @@ extern const MiLightRemoteConfig FUT089Config; //rgb+cct B8 / FUT089 extern const MiLightRemoteConfig FUT098Config; //rgb extern const MiLightRemoteConfig FUT091Config; //v2 cct extern const MiLightRemoteConfig FUT020Config; +extern const MiLightRemoteConfig CasaluxConfig; +extern const MiLightRemoteConfig NLGConfig; #endif diff --git a/lib/MiLight/NLGPacketFormatter.cpp b/lib/MiLight/NLGPacketFormatter.cpp new file mode 100644 index 00000000..8f5ec3b4 --- /dev/null +++ b/lib/MiLight/NLGPacketFormatter.cpp @@ -0,0 +1,211 @@ +#include +#include + +bool NLGPacketFormatter::canHandle(const uint8_t *packet, const size_t len) { + return len == packetLength && packet[0] == 0x00; +} + +/* +00 01 02 03 04 05 06 07 08 09 +======================= =CRC= +07 00 20 FE 00 01 B1 00 All-On +07 00 20 FE 00 02 B3 00 All-Off + +07 00 20 FE 07 07 B5 00 Group1 An +07 00 20 FE 00 08 B7 00 Group1 Aus + +07 00 20 FE 09 09 B9 00 Group2 An +07 00 20 FE 00 0A BB 00 Group2 Aus + +07 00 20 FE 0B 0B BD 00 Group3 An +07 00 20 FE 00 0C BF 00 Group3 Aus + +07 00 20 FE 0D 0D C1 00 Group4 An +07 00 20 FE 00 0E C3 00 Group4 Aus + +07 00 20 FE 00 03 C5 00 heller +07 00 20 FE 00 06 C7 00 dunkler + +07 00 20 FE 00 04 CB 00 wärmer +07 00 20 FE 00 05 CD 00 kälter +*/ + +void NLGPacketFormatter::initializePacket(uint8_t* packet) { + size_t packetPtr = 0; + + // Byte 0: Packet length = 7 bytes + + // Byte 1: NLG protocol???? + packet[packetPtr++] = 0x00; + + // Byte 2 and 3: Device ID + packet[packetPtr++] = deviceId >> 8; + packet[packetPtr++] = deviceId & 0xFF; + + // Byte 4: Active Group filled in later + packet[packetPtr++] = 0x00; //groupToGroupId(groupId); + + + // Byte 5: Bulb command, filled in later + packet[packetPtr++] = 0x00; + + + // Byte 6: Packet sequence number 0..254 + sequenceNum += 2; + packet[packetPtr++] = sequenceNum; + + // Byte 7: Zero + packet[packetPtr++] = 0x00; + + // Byte 8: CRC LSB + // Byte 9: CRC MSB +} + +void NLGPacketFormatter::finalizePacket(uint8_t* packet) { +} + +void NLGPacketFormatter::updateBrightness(uint8_t value) { + const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_NLG); + int8_t knownValue = (state != NULL && state->isSetBrightness()) ? state->getBrightness() : -1; + + Serial.printf("Brightness %d\n", knownValue); + + valueByStepFunction( + &PacketFormatter::increaseBrightness, + &PacketFormatter::decreaseBrightness, + 13, + value, + knownValue + ); + +} + +void NLGPacketFormatter::updateTemperature(uint8_t value) { + const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_NLG); + int8_t knownValue = (state != NULL && state->isSetKelvin()) ? state->getKelvin() : -1; + + Serial.printf("Temp %d\n", knownValue); + + valueByStepFunction( + &PacketFormatter::increaseTemperature, + &PacketFormatter::decreaseTemperature, + 13, + value, + knownValue + ); + + +} + +void NLGPacketFormatter::command(uint8_t command, uint8_t arg) { + // arg1 1 = send active group + pushPacket(); + if(arg) currentPacket[3] = groupToGroupId(groupId)+1; + else currentPacket[3] = 0; + + currentPacket[4] = command; +} + +void NLGPacketFormatter::updateStatus(MiLightStatus status, uint8_t groupId) { + command(groupToGroupId(groupId) +1 +status, !status); +} + + +uint8_t NLGPacketFormatter::groupToGroupId(uint8_t group){ + switch(group) { + case 1: + return 0x06; + case 2: + return 0x08; + case 3: + return 0x0A; + case 4: + return 0x0C; + default: + return 0x00; + } +} + +BulbId NLGPacketFormatter::parsePacket(const uint8_t* packet, JsonObject result) { + uint8_t command = packet[4]; + + if(command > 6) { // On/Off + if(command != 0xEE) { // If not Button release + groupId = groupIdToGroup(command); // groupid only included if command >6 + + result[GroupStateFieldNames::STATE] = command & 0x01 ? "ON" : "OFF"; + } + + } else { + // DPAD + switch(command){ + case 0x03: + result[GroupStateFieldNames::COMMAND] = "brightness_up"; + break; + + case 0x04: + result[GroupStateFieldNames::COMMAND] = MiLightCommandNames::TEMPERATURE_DOWN; + break; + + case 0x05: + result[GroupStateFieldNames::COMMAND] = MiLightCommandNames::TEMPERATURE_UP; + break; + + case 0x06: + result[GroupStateFieldNames::COMMAND] = "brightness_down"; + break; + + default: + result["button_id"] = command; + break; + } + } + + BulbId bulbId((packet[1] << 8) | packet[2], groupId, REMOTE_TYPE_NLG); + + sequenceNum = packet[5]; + + return bulbId; +} + +uint8_t NLGPacketFormatter::groupIdToGroup(uint8_t groupId){ + printf("find group: 0x%x\n", groupId); + switch((groupId -1) & 0b00001110) { + case 0x06: + return 1; + case 0x08: + return 2; + case 0x0A: + return 3; + case 0x0C: + return 4; + default: + printf("group undefined: 0x%x\n", (groupId -1) & 0b00001110); + return 255; + } +} + +void NLGPacketFormatter::increaseTemperature() { + command(0x05, 1); +} + +void NLGPacketFormatter::decreaseTemperature() { + command(0x04, 1); +} + +void NLGPacketFormatter::increaseBrightness() { + command(0x03, 1); +} + +void NLGPacketFormatter::decreaseBrightness() { + command(0x06, 1); +} + +void NLGPacketFormatter::format(uint8_t const* packet, char* buffer) { + buffer += sprintf_P(buffer, PSTR("Byte 1 (00) : %02X\n"), packet[0]) ; + buffer += sprintf_P(buffer, PSTR("Byte 2,3 Device ID: %02X%02X\n"), packet[1], packet[2]); + buffer += sprintf_P(buffer, PSTR("Byte 4 Group : %02X\n"), packet[3]); + buffer += sprintf_P(buffer, PSTR("Byte 5 CMD : %02X\n"), packet[4]); + buffer += sprintf_P(buffer, PSTR("Byte 6 Seq. Num. : %02X\n"), packet[5]); + buffer += sprintf_P(buffer, PSTR("Byte 7 (00) : %02X\n"), packet[6]); +} diff --git a/lib/MiLight/NLGPacketFormatter.h b/lib/MiLight/NLGPacketFormatter.h new file mode 100644 index 00000000..6aaa57f7 --- /dev/null +++ b/lib/MiLight/NLGPacketFormatter.h @@ -0,0 +1,30 @@ +#include + +#ifndef _NLG_PACKET_FORMATTER_H +#define _NLG_PACKET_FORMATTER_H + +class NLGPacketFormatter : public PacketFormatter { +public: + NLGPacketFormatter() + : PacketFormatter(REMOTE_TYPE_NLG, 7, 20) + { } + + virtual bool canHandle(const uint8_t* packet, const size_t len); + + virtual void command(uint8_t command, uint8_t arg); + virtual void updateStatus(MiLightStatus status, uint8_t groupId); + virtual void updateTemperature(uint8_t value); + virtual void increaseTemperature(); + virtual void decreaseTemperature(); + virtual void updateBrightness(uint8_t value); + virtual void increaseBrightness(); + virtual void decreaseBrightness(); + virtual void format(uint8_t const* packet, char* buffer); + virtual void initializePacket(uint8_t* packet); + virtual void finalizePacket(uint8_t* packet); + virtual BulbId parsePacket(const uint8_t* packet, JsonObject result); + static uint8_t groupToGroupId(uint8_t group); + static uint8_t groupIdToGroup(uint8_t groupId); +}; + +#endif \ No newline at end of file diff --git a/lib/MiLight/PacketFormatter.cpp b/lib/MiLight/PacketFormatter.cpp index 0b370d2f..4220f9e5 100644 --- a/lib/MiLight/PacketFormatter.cpp +++ b/lib/MiLight/PacketFormatter.cpp @@ -19,6 +19,8 @@ uint8_t* PacketStream::next() { return packet; } + +// For what is maxPackets ???? PacketFormatter::PacketFormatter(const MiLightRemoteType deviceType, const size_t packetLength, const size_t maxPackets) : deviceType(deviceType), packetLength(packetLength), @@ -109,6 +111,9 @@ void PacketFormatter::valueByStepFunction(StepFunction increase, StepFunction de StepFunction fn; size_t numCommands = 0; + // There was a false calculation: "value / steps" should be "value / (100 / steps)" + uint8_t stepSize = 100 / numSteps; + // If current value is not known, drive down to minimum value. Then we can assume that we // know the state (it'll be 0). if (knownValue == -1) { @@ -118,12 +123,15 @@ void PacketFormatter::valueByStepFunction(StepFunction increase, StepFunction de fn = increase; numCommands = targetValue; + } else if (targetValue < knownValue) { fn = decrease; - numCommands = (knownValue - targetValue); + numCommands = (knownValue - targetValue) / stepSize; + } else if (targetValue > knownValue) { fn = increase; - numCommands = (targetValue - knownValue); + numCommands = (targetValue - knownValue) / stepSize; + } else { return; } diff --git a/lib/MiLight/PacketFormatter.h b/lib/MiLight/PacketFormatter.h index 9a4348e2..90fd1725 100644 --- a/lib/MiLight/PacketFormatter.h +++ b/lib/MiLight/PacketFormatter.h @@ -13,7 +13,10 @@ // Most packets sent is for CCT bulbs, which always includes 10 down commands // and can include up to 10 up commands. CCT packets are 7 bytes. // (10 * 7) + (10 * 7) = 140 -#define PACKET_FORMATTER_BUFFER_SIZE 140 +// unreliable size calculation !!! +// Packets can be 11 Bytes and repeats can set to 30 via GUI, impossible to calc max buffer size, +// so declare just high enough +#define PACKET_FORMATTER_BUFFER_SIZE 4096 struct PacketStream { PacketStream(); diff --git a/lib/MiLight/RadioSwitchboard.cpp b/lib/MiLight/RadioSwitchboard.cpp index a79f8a11..a8620b10 100644 --- a/lib/MiLight/RadioSwitchboard.cpp +++ b/lib/MiLight/RadioSwitchboard.cpp @@ -6,6 +6,18 @@ RadioSwitchboard::RadioSwitchboard( Settings& settings ) { for (size_t i = 0; i < MiLightRadioConfig::NUM_CONFIGS; i++) { + + // Use only active configs + if(settings.activeRadioConfigs.size() > 0) { + bool config_active = false; + + for (uint8_t y : settings.activeRadioConfigs){ + if(y == i) config_active = true; + } + + if(!config_active) continue; + } + std::shared_ptr radio = radioFactory->create(MiLightRadioConfig::ALL_CONFIGS[i]); radio->begin(); radios.push_back(radio); diff --git a/lib/MiLight/RgbPacketFormatter.cpp b/lib/MiLight/RgbPacketFormatter.cpp index c05ed8b6..06d4d556 100644 --- a/lib/MiLight/RgbPacketFormatter.cpp +++ b/lib/MiLight/RgbPacketFormatter.cpp @@ -49,13 +49,13 @@ void RgbPacketFormatter::updateColorRaw(uint8_t value) { void RgbPacketFormatter::updateBrightness(uint8_t value) { const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_RGB); - int8_t knownValue = (state != NULL && state->isSetBrightness()) ? state->getBrightness() / RGB_INTERVALS : -1; + int8_t knownValue = (state != NULL && state->isSetBrightness()) ? state->getBrightness() : -1; valueByStepFunction( &PacketFormatter::increaseBrightness, &PacketFormatter::decreaseBrightness, RGB_INTERVALS, - value / RGB_INTERVALS, + value, knownValue ); } diff --git a/lib/Radio/LT8900MiLightRadio.h b/lib/Radio/LT8900MiLightRadio.h index 09655616..ab89a471 100644 --- a/lib/Radio/LT8900MiLightRadio.h +++ b/lib/Radio/LT8900MiLightRadio.h @@ -77,8 +77,8 @@ class LT8900MiLightRadio : public MiLightRadio { const MiLightRadioConfig& _config; uint8_t _channel; - uint8_t _packet[10]; - uint8_t _out_packet[10]; + uint8_t _packet[11]; + uint8_t _out_packet[11]; bool _waiting; int _dupes_received; size_t _currentPacketLen; diff --git a/lib/Radio/MiLightRadioConfig.cpp b/lib/Radio/MiLightRadioConfig.cpp index 9af77447..5c6781d7 100644 --- a/lib/Radio/MiLightRadioConfig.cpp +++ b/lib/Radio/MiLightRadioConfig.cpp @@ -1,9 +1,13 @@ #include MiLightRadioConfig MiLightRadioConfig::ALL_CONFIGS[] = { + //MiLightRadioConfig(syncword0, syncword3, packetLength, channel0, channel1, channel2, preamble, trailer, enableFEC23) MiLightRadioConfig(0x147A, 0x258B, 7, 9, 40, 71, 0xAA, 0x05), // rgbw MiLightRadioConfig(0x050A, 0x55AA, 7, 4, 39, 74, 0xAA, 0x05), // cct MiLightRadioConfig(0x7236, 0x1809, 9, 8, 39, 70, 0xAA, 0x05), // rgb+cct, fut089 MiLightRadioConfig(0x9AAB, 0xBCCD, 6, 3, 38, 73, 0x55, 0x0A), // rgb - MiLightRadioConfig(0x50A0, 0xAA55, 6, 6, 41, 76, 0xAA, 0x0A) // FUT020 + MiLightRadioConfig(0x50A0, 0xAA55, 6, 6, 41, 76, 0xAA, 0x0A), // FUT020 + MiLightRadioConfig(0x4231, 0xdecf, 10, 24, 48, 72, 0x55, 0x0A), // casalux + MiLightRadioConfig(0x6162, 0x6768, 7, 30, 30, 30, 0xAA, 0x05, true) // NLG, Neuhaus Lightning Group, Paul Nauhaus }; + \ No newline at end of file diff --git a/lib/Radio/MiLightRadioConfig.h b/lib/Radio/MiLightRadioConfig.h index cd512da0..b67e9366 100644 --- a/lib/Radio/MiLightRadioConfig.h +++ b/lib/Radio/MiLightRadioConfig.h @@ -6,7 +6,7 @@ #ifndef _MILIGHT_RADIO_CONFIG #define _MILIGHT_RADIO_CONFIG -#define MILIGHT_MAX_PACKET_LENGTH 9 +#define MILIGHT_MAX_PACKET_LENGTH 15 class MiLightRadioConfig { public: @@ -28,6 +28,12 @@ class MiLightRadioConfig { // // In general, this should be set to 5 unless packets that should be showing up are // mysteriously not present. + // + // FEC23 is FEC2/3 is Hamming (15,10) + // 10 databits followed by 5 bit syndrome + // length +50% + // + static const uint8_t SYNCWORD_LENGTH = 5; MiLightRadioConfig( @@ -38,10 +44,12 @@ class MiLightRadioConfig { const uint8_t channel1, const uint8_t channel2, const uint8_t preamble, - const uint8_t trailer + const uint8_t trailer, + const bool enable_fec23 = false ) : syncword0(syncword0) , syncword3(syncword3) , packetLength(packetLength) + , enable_fec23(enable_fec23) { channels[0] = channel0; channels[1] = channel1; @@ -75,8 +83,9 @@ class MiLightRadioConfig { uint16_t syncword0, syncword3; const size_t packetLength; + const bool enable_fec23; - static const size_t NUM_CONFIGS = 5; + static const size_t NUM_CONFIGS = 7; static MiLightRadioConfig ALL_CONFIGS[NUM_CONFIGS]; }; diff --git a/lib/Radio/NRF24MiLightRadio.cpp b/lib/Radio/NRF24MiLightRadio.cpp index b2fefc9f..5900abcd 100644 --- a/lib/Radio/NRF24MiLightRadio.cpp +++ b/lib/Radio/NRF24MiLightRadio.cpp @@ -3,7 +3,21 @@ #include #include -#define PACKET_ID(packet, packet_length) ( (packet[1] << 8) | packet[packet_length - 1] ) +/* +This is very unreliable. NLG Packets have byte1 = 0 and len-1 byte = 0 !!!!!!! +Take me hours to find this prob +Packet_id should be generated by hashing of ALL BYTES +maybe a macro isnt enough +*/ +//#define PACKET_ID(packet, packet_length) ( (packet[packet_length] ^ packet[packet_length +1]) << 24 ^ (packet[packet_length +2] ^ packet[packet_length +3]) << 16 ^ (packet[packet_length +4] ^ packet[packet_length +5]) << 8 ) + +uint32_t PACKET_ID(uint8_t _packet[], size_t packet_length){ + uint32_t ret = _packet[0]; + ret |= _packet[1] << 8 | _packet[2] << 16 | _packet[3] << 24; + ret ^= _packet[4] << 8 | _packet[5] << 16 | _packet[6] << 24; + + return ret; +} NRF24MiLightRadio::NRF24MiLightRadio( RF24& rf24, @@ -46,6 +60,8 @@ int NRF24MiLightRadio::configure() { return retval; } + _pl1167.enableFEC23(_config.enable_fec23); + return 0; } diff --git a/lib/Radio/NRF24MiLightRadio.h b/lib/Radio/NRF24MiLightRadio.h index b7900e51..6e41a199 100644 --- a/lib/Radio/NRF24MiLightRadio.h +++ b/lib/Radio/NRF24MiLightRadio.h @@ -33,7 +33,7 @@ class NRF24MiLightRadio : public MiLightRadio { int resend(); int configure(); const MiLightRadioConfig& config(); - + private: const std::vector& channels; const size_t listenChannelIx; @@ -42,8 +42,8 @@ class NRF24MiLightRadio : public MiLightRadio { const MiLightRadioConfig& _config; uint32_t _prev_packet_id; - uint8_t _packet[10]; - uint8_t _out_packet[10]; + uint8_t _packet[15]; + uint8_t _out_packet[15]; bool _waiting; int _dupes_received; }; diff --git a/lib/Radio/PL1167_FEC23.cpp b/lib/Radio/PL1167_FEC23.cpp new file mode 100644 index 00000000..7b86cf19 --- /dev/null +++ b/lib/Radio/PL1167_FEC23.cpp @@ -0,0 +1,76 @@ +#include +#include + +/* + This class is to implement the Hamming 15,10 + for Forward Error Correction FEC23 by pl1167 + + created: 10.08.2023 + author: Michael Balen + inspired by http://www.finetune.co.jp/~lyuka/technote/ecc/ham1510/ +*/ + +uint32_t PL1167_FEC23::getSyndrome(){ + syndrome = code ^ encodeTable[code >> ECC_LEN]; + status = errorTable[syndrome]; + return syndrome; +}; + +uint32_t PL1167_FEC23::correct(){ + code ^= burstErrorCorrection ? status >> 16 : status ; + code &= CODE_MASK; + return code; +}; + +uint32_t PL1167_FEC23::encode(uint16_t data){ + code = encodeTable[data & DATA_MASK]; + return code; +}; + +uint16_t PL1167_FEC23::decode(){ + return (code >> ECC_LEN) & DATA_MASK; +}; + +size_t PL1167_FEC23::encodeMessage(uint8_t data[], size_t numValues){ + BitstreamConvert converter(8, 10); + converter.convert(data, numValues); + uint16_t * out = converter.get(); + + for(uint8_t i = 0; i < converter.sizeOut; i++){ + out[i] = encode(out[i]); + } + + BitstreamConvert converter2(15, 8); + converter2.convert(out, converter.sizeOut); + out = converter2.get(); + + for(uint8_t i = 0; i < converter2.sizeOut; i++){ + data[i] = out[i]; + } + + return converter2.sizeOut; +}; + +size_t PL1167_FEC23::decodeMessage(uint8_t data[], size_t numValues){ + BitstreamConvert converter(8, 15); + converter.convert(data, numValues); + uint16_t * out = converter.get(); + + for(uint8_t i = 0; i < converter.sizeOut; i++){ + code = out[i]; + getSyndrome(); + correct(); + out[i] = decode(); + } + + BitstreamConvert converter2(10, 8); + converter2.convert(out, converter.sizeOut); + out = converter2.get(); + + for(uint8_t i = 0; i < converter2.sizeOut; i++){ + data[i] = out[i]; + } + + return converter2.sizeOut; +}; + diff --git a/lib/Radio/PL1167_FEC23.h b/lib/Radio/PL1167_FEC23.h new file mode 100644 index 00000000..c2f60a36 --- /dev/null +++ b/lib/Radio/PL1167_FEC23.h @@ -0,0 +1,305 @@ +#include + +#ifndef _PL1167_FEC23_H +#define _PL1167_FEC23_H + +// encode tables are static to prevent memory consumption +// on reinitialization by the main class + +static const uint16_t encodeTable[0x0400] = { +0x00, 0x35, 0x5f, 0x6a, +0x8b, 0xbe, 0xd4, 0xe1, +0x116, 0x123, 0x149, 0x17c, +0x19d, 0x1a8, 0x1c2, 0x1f7, +0x219, 0x22c, 0x246, 0x273, +0x292, 0x2a7, 0x2cd, 0x2f8, +0x30f, 0x33a, 0x350, 0x365, +0x384, 0x3b1, 0x3db, 0x3ee, +0x407, 0x432, 0x458, 0x46d, +0x48c, 0x4b9, 0x4d3, 0x4e6, +0x511, 0x524, 0x54e, 0x57b, +0x59a, 0x5af, 0x5c5, 0x5f0, +0x61e, 0x62b, 0x641, 0x674, +0x695, 0x6a0, 0x6ca, 0x6ff, +0x708, 0x73d, 0x757, 0x762, +0x783, 0x7b6, 0x7dc, 0x7e9, +0x80e, 0x83b, 0x851, 0x864, +0x885, 0x8b0, 0x8da, 0x8ef, +0x918, 0x92d, 0x947, 0x972, +0x993, 0x9a6, 0x9cc, 0x9f9, +0xa17, 0xa22, 0xa48, 0xa7d, +0xa9c, 0xaa9, 0xac3, 0xaf6, +0xb01, 0xb34, 0xb5e, 0xb6b, +0xb8a, 0xbbf, 0xbd5, 0xbe0, +0xc09, 0xc3c, 0xc56, 0xc63, +0xc82, 0xcb7, 0xcdd, 0xce8, +0xd1f, 0xd2a, 0xd40, 0xd75, +0xd94, 0xda1, 0xdcb, 0xdfe, +0xe10, 0xe25, 0xe4f, 0xe7a, +0xe9b, 0xeae, 0xec4, 0xef1, +0xf06, 0xf33, 0xf59, 0xf6c, +0xf8d, 0xfb8, 0xfd2, 0xfe7, +0x101c, 0x1029, 0x1043, 0x1076, +0x1097, 0x10a2, 0x10c8, 0x10fd, +0x110a, 0x113f, 0x1155, 0x1160, +0x1181, 0x11b4, 0x11de, 0x11eb, +0x1205, 0x1230, 0x125a, 0x126f, +0x128e, 0x12bb, 0x12d1, 0x12e4, +0x1313, 0x1326, 0x134c, 0x1379, +0x1398, 0x13ad, 0x13c7, 0x13f2, +0x141b, 0x142e, 0x1444, 0x1471, +0x1490, 0x14a5, 0x14cf, 0x14fa, +0x150d, 0x1538, 0x1552, 0x1567, +0x1586, 0x15b3, 0x15d9, 0x15ec, +0x1602, 0x1637, 0x165d, 0x1668, +0x1689, 0x16bc, 0x16d6, 0x16e3, +0x1714, 0x1721, 0x174b, 0x177e, +0x179f, 0x17aa, 0x17c0, 0x17f5, +0x1812, 0x1827, 0x184d, 0x1878, +0x1899, 0x18ac, 0x18c6, 0x18f3, +0x1904, 0x1931, 0x195b, 0x196e, +0x198f, 0x19ba, 0x19d0, 0x19e5, +0x1a0b, 0x1a3e, 0x1a54, 0x1a61, +0x1a80, 0x1ab5, 0x1adf, 0x1aea, +0x1b1d, 0x1b28, 0x1b42, 0x1b77, +0x1b96, 0x1ba3, 0x1bc9, 0x1bfc, +0x1c15, 0x1c20, 0x1c4a, 0x1c7f, +0x1c9e, 0x1cab, 0x1cc1, 0x1cf4, +0x1d03, 0x1d36, 0x1d5c, 0x1d69, +0x1d88, 0x1dbd, 0x1dd7, 0x1de2, +0x1e0c, 0x1e39, 0x1e53, 0x1e66, +0x1e87, 0x1eb2, 0x1ed8, 0x1eed, +0x1f1a, 0x1f2f, 0x1f45, 0x1f70, +0x1f91, 0x1fa4, 0x1fce, 0x1ffb, +0x200d, 0x2038, 0x2052, 0x2067, +0x2086, 0x20b3, 0x20d9, 0x20ec, +0x211b, 0x212e, 0x2144, 0x2171, +0x2190, 0x21a5, 0x21cf, 0x21fa, +0x2214, 0x2221, 0x224b, 0x227e, +0x229f, 0x22aa, 0x22c0, 0x22f5, +0x2302, 0x2337, 0x235d, 0x2368, +0x2389, 0x23bc, 0x23d6, 0x23e3, +0x240a, 0x243f, 0x2455, 0x2460, +0x2481, 0x24b4, 0x24de, 0x24eb, +0x251c, 0x2529, 0x2543, 0x2576, +0x2597, 0x25a2, 0x25c8, 0x25fd, +0x2613, 0x2626, 0x264c, 0x2679, +0x2698, 0x26ad, 0x26c7, 0x26f2, +0x2705, 0x2730, 0x275a, 0x276f, +0x278e, 0x27bb, 0x27d1, 0x27e4, +0x2803, 0x2836, 0x285c, 0x2869, +0x2888, 0x28bd, 0x28d7, 0x28e2, +0x2915, 0x2920, 0x294a, 0x297f, +0x299e, 0x29ab, 0x29c1, 0x29f4, +0x2a1a, 0x2a2f, 0x2a45, 0x2a70, +0x2a91, 0x2aa4, 0x2ace, 0x2afb, +0x2b0c, 0x2b39, 0x2b53, 0x2b66, +0x2b87, 0x2bb2, 0x2bd8, 0x2bed, +0x2c04, 0x2c31, 0x2c5b, 0x2c6e, +0x2c8f, 0x2cba, 0x2cd0, 0x2ce5, +0x2d12, 0x2d27, 0x2d4d, 0x2d78, +0x2d99, 0x2dac, 0x2dc6, 0x2df3, +0x2e1d, 0x2e28, 0x2e42, 0x2e77, +0x2e96, 0x2ea3, 0x2ec9, 0x2efc, +0x2f0b, 0x2f3e, 0x2f54, 0x2f61, +0x2f80, 0x2fb5, 0x2fdf, 0x2fea, +0x3011, 0x3024, 0x304e, 0x307b, +0x309a, 0x30af, 0x30c5, 0x30f0, +0x3107, 0x3132, 0x3158, 0x316d, +0x318c, 0x31b9, 0x31d3, 0x31e6, +0x3208, 0x323d, 0x3257, 0x3262, +0x3283, 0x32b6, 0x32dc, 0x32e9, +0x331e, 0x332b, 0x3341, 0x3374, +0x3395, 0x33a0, 0x33ca, 0x33ff, +0x3416, 0x3423, 0x3449, 0x347c, +0x349d, 0x34a8, 0x34c2, 0x34f7, +0x3500, 0x3535, 0x355f, 0x356a, +0x358b, 0x35be, 0x35d4, 0x35e1, +0x360f, 0x363a, 0x3650, 0x3665, +0x3684, 0x36b1, 0x36db, 0x36ee, +0x3719, 0x372c, 0x3746, 0x3773, +0x3792, 0x37a7, 0x37cd, 0x37f8, +0x381f, 0x382a, 0x3840, 0x3875, +0x3894, 0x38a1, 0x38cb, 0x38fe, +0x3909, 0x393c, 0x3956, 0x3963, +0x3982, 0x39b7, 0x39dd, 0x39e8, +0x3a06, 0x3a33, 0x3a59, 0x3a6c, +0x3a8d, 0x3ab8, 0x3ad2, 0x3ae7, +0x3b10, 0x3b25, 0x3b4f, 0x3b7a, +0x3b9b, 0x3bae, 0x3bc4, 0x3bf1, +0x3c18, 0x3c2d, 0x3c47, 0x3c72, +0x3c93, 0x3ca6, 0x3ccc, 0x3cf9, +0x3d0e, 0x3d3b, 0x3d51, 0x3d64, +0x3d85, 0x3db0, 0x3dda, 0x3def, +0x3e01, 0x3e34, 0x3e5e, 0x3e6b, +0x3e8a, 0x3ebf, 0x3ed5, 0x3ee0, +0x3f17, 0x3f22, 0x3f48, 0x3f7d, +0x3f9c, 0x3fa9, 0x3fc3, 0x3ff6, +0x401a, 0x402f, 0x4045, 0x4070, +0x4091, 0x40a4, 0x40ce, 0x40fb, +0x410c, 0x4139, 0x4153, 0x4166, +0x4187, 0x41b2, 0x41d8, 0x41ed, +0x4203, 0x4236, 0x425c, 0x4269, +0x4288, 0x42bd, 0x42d7, 0x42e2, +0x4315, 0x4320, 0x434a, 0x437f, +0x439e, 0x43ab, 0x43c1, 0x43f4, +0x441d, 0x4428, 0x4442, 0x4477, +0x4496, 0x44a3, 0x44c9, 0x44fc, +0x450b, 0x453e, 0x4554, 0x4561, +0x4580, 0x45b5, 0x45df, 0x45ea, +0x4604, 0x4631, 0x465b, 0x466e, +0x468f, 0x46ba, 0x46d0, 0x46e5, +0x4712, 0x4727, 0x474d, 0x4778, +0x4799, 0x47ac, 0x47c6, 0x47f3, +0x4814, 0x4821, 0x484b, 0x487e, +0x489f, 0x48aa, 0x48c0, 0x48f5, +0x4902, 0x4937, 0x495d, 0x4968, +0x4989, 0x49bc, 0x49d6, 0x49e3, +0x4a0d, 0x4a38, 0x4a52, 0x4a67, +0x4a86, 0x4ab3, 0x4ad9, 0x4aec, +0x4b1b, 0x4b2e, 0x4b44, 0x4b71, +0x4b90, 0x4ba5, 0x4bcf, 0x4bfa, +0x4c13, 0x4c26, 0x4c4c, 0x4c79, +0x4c98, 0x4cad, 0x4cc7, 0x4cf2, +0x4d05, 0x4d30, 0x4d5a, 0x4d6f, +0x4d8e, 0x4dbb, 0x4dd1, 0x4de4, +0x4e0a, 0x4e3f, 0x4e55, 0x4e60, +0x4e81, 0x4eb4, 0x4ede, 0x4eeb, +0x4f1c, 0x4f29, 0x4f43, 0x4f76, +0x4f97, 0x4fa2, 0x4fc8, 0x4ffd, +0x5006, 0x5033, 0x5059, 0x506c, +0x508d, 0x50b8, 0x50d2, 0x50e7, +0x5110, 0x5125, 0x514f, 0x517a, +0x519b, 0x51ae, 0x51c4, 0x51f1, +0x521f, 0x522a, 0x5240, 0x5275, +0x5294, 0x52a1, 0x52cb, 0x52fe, +0x5309, 0x533c, 0x5356, 0x5363, +0x5382, 0x53b7, 0x53dd, 0x53e8, +0x5401, 0x5434, 0x545e, 0x546b, +0x548a, 0x54bf, 0x54d5, 0x54e0, +0x5517, 0x5522, 0x5548, 0x557d, +0x559c, 0x55a9, 0x55c3, 0x55f6, +0x5618, 0x562d, 0x5647, 0x5672, +0x5693, 0x56a6, 0x56cc, 0x56f9, +0x570e, 0x573b, 0x5751, 0x5764, +0x5785, 0x57b0, 0x57da, 0x57ef, +0x5808, 0x583d, 0x5857, 0x5862, +0x5883, 0x58b6, 0x58dc, 0x58e9, +0x591e, 0x592b, 0x5941, 0x5974, +0x5995, 0x59a0, 0x59ca, 0x59ff, +0x5a11, 0x5a24, 0x5a4e, 0x5a7b, +0x5a9a, 0x5aaf, 0x5ac5, 0x5af0, +0x5b07, 0x5b32, 0x5b58, 0x5b6d, +0x5b8c, 0x5bb9, 0x5bd3, 0x5be6, +0x5c0f, 0x5c3a, 0x5c50, 0x5c65, +0x5c84, 0x5cb1, 0x5cdb, 0x5cee, +0x5d19, 0x5d2c, 0x5d46, 0x5d73, +0x5d92, 0x5da7, 0x5dcd, 0x5df8, +0x5e16, 0x5e23, 0x5e49, 0x5e7c, +0x5e9d, 0x5ea8, 0x5ec2, 0x5ef7, +0x5f00, 0x5f35, 0x5f5f, 0x5f6a, +0x5f8b, 0x5fbe, 0x5fd4, 0x5fe1, +0x6017, 0x6022, 0x6048, 0x607d, +0x609c, 0x60a9, 0x60c3, 0x60f6, +0x6101, 0x6134, 0x615e, 0x616b, +0x618a, 0x61bf, 0x61d5, 0x61e0, +0x620e, 0x623b, 0x6251, 0x6264, +0x6285, 0x62b0, 0x62da, 0x62ef, +0x6318, 0x632d, 0x6347, 0x6372, +0x6393, 0x63a6, 0x63cc, 0x63f9, +0x6410, 0x6425, 0x644f, 0x647a, +0x649b, 0x64ae, 0x64c4, 0x64f1, +0x6506, 0x6533, 0x6559, 0x656c, +0x658d, 0x65b8, 0x65d2, 0x65e7, +0x6609, 0x663c, 0x6656, 0x6663, +0x6682, 0x66b7, 0x66dd, 0x66e8, +0x671f, 0x672a, 0x6740, 0x6775, +0x6794, 0x67a1, 0x67cb, 0x67fe, +0x6819, 0x682c, 0x6846, 0x6873, +0x6892, 0x68a7, 0x68cd, 0x68f8, +0x690f, 0x693a, 0x6950, 0x6965, +0x6984, 0x69b1, 0x69db, 0x69ee, +0x6a00, 0x6a35, 0x6a5f, 0x6a6a, +0x6a8b, 0x6abe, 0x6ad4, 0x6ae1, +0x6b16, 0x6b23, 0x6b49, 0x6b7c, +0x6b9d, 0x6ba8, 0x6bc2, 0x6bf7, +0x6c1e, 0x6c2b, 0x6c41, 0x6c74, +0x6c95, 0x6ca0, 0x6cca, 0x6cff, +0x6d08, 0x6d3d, 0x6d57, 0x6d62, +0x6d83, 0x6db6, 0x6ddc, 0x6de9, +0x6e07, 0x6e32, 0x6e58, 0x6e6d, +0x6e8c, 0x6eb9, 0x6ed3, 0x6ee6, +0x6f11, 0x6f24, 0x6f4e, 0x6f7b, +0x6f9a, 0x6faf, 0x6fc5, 0x6ff0, +0x700b, 0x703e, 0x7054, 0x7061, +0x7080, 0x70b5, 0x70df, 0x70ea, +0x711d, 0x7128, 0x7142, 0x7177, +0x7196, 0x71a3, 0x71c9, 0x71fc, +0x7212, 0x7227, 0x724d, 0x7278, +0x7299, 0x72ac, 0x72c6, 0x72f3, +0x7304, 0x7331, 0x735b, 0x736e, +0x738f, 0x73ba, 0x73d0, 0x73e5, +0x740c, 0x7439, 0x7453, 0x7466, +0x7487, 0x74b2, 0x74d8, 0x74ed, +0x751a, 0x752f, 0x7545, 0x7570, +0x7591, 0x75a4, 0x75ce, 0x75fb, +0x7615, 0x7620, 0x764a, 0x767f, +0x769e, 0x76ab, 0x76c1, 0x76f4, +0x7703, 0x7736, 0x775c, 0x7769, +0x7788, 0x77bd, 0x77d7, 0x77e2, +0x7805, 0x7830, 0x785a, 0x786f, +0x788e, 0x78bb, 0x78d1, 0x78e4, +0x7913, 0x7926, 0x794c, 0x7979, +0x7998, 0x79ad, 0x79c7, 0x79f2, +0x7a1c, 0x7a29, 0x7a43, 0x7a76, +0x7a97, 0x7aa2, 0x7ac8, 0x7afd, +0x7b0a, 0x7b3f, 0x7b55, 0x7b60, +0x7b81, 0x7bb4, 0x7bde, 0x7beb, +0x7c02, 0x7c37, 0x7c5d, 0x7c68, +0x7c89, 0x7cbc, 0x7cd6, 0x7ce3, +0x7d14, 0x7d21, 0x7d4b, 0x7d7e, +0x7d9f, 0x7daa, 0x7dc0, 0x7df5, +0x7e1b, 0x7e2e, 0x7e44, 0x7e71, +0x7e90, 0x7ea5, 0x7ecf, 0x7efa, +0x7f0d, 0x7f38, 0x7f52, 0x7f67, +0x7f86, 0x7fb3, 0x7fd9 +}; + +static const uint32_t errorTable[32] = { + 0x00000000, 0x00000001, 0x00000002, 0x80030000, + 0x00000004, 0x80300000, 0x80060006, 0x00000400, + 0x00000008, 0x8c000000, 0x80600060, 0x00000080, + 0x800c0000, 0x00002000, 0x00000800, 0x83000000, + 0x00000010, 0xb0000000, 0x98000000, 0x93008000, + 0x80c00000, 0x00000020, 0x00000100, 0xe0000000, + 0x80180000, 0x00000200, 0x00004000, 0xc0010000, + 0x00001000, 0x81800000, 0x86000000, 0x00000040 + }; + + +class PL1167_FEC23 { + public: + static const size_t GEN_POLY = 0x6a00; + static const size_t BIT_MASK = 0x4000; + static const size_t CODE_MASK = 0x7fff; + static const size_t DATA_MASK = 0x03ff; + static const size_t N2D = 0x0400; + static const size_t DATA_LEN = 10; + static const size_t ECC_LEN = 5; + uint16_t code; + uint32_t syndrome; + uint32_t status; + bool burstErrorCorrection = false; + + uint32_t getSyndrome(); + uint32_t correct(); + uint32_t encode(uint16_t data); + uint16_t decode(); + size_t encodeMessage(uint8_t data[], size_t numValues); + size_t decodeMessage(uint8_t data[], size_t numValues); + + private: + +}; + +#endif diff --git a/lib/Radio/PL1167_nRF24.cpp b/lib/Radio/PL1167_nRF24.cpp index dc854747..02ad56ec 100644 --- a/lib/Radio/PL1167_nRF24.cpp +++ b/lib/Radio/PL1167_nRF24.cpp @@ -10,9 +10,11 @@ * */ -#include "PL1167_nRF24.h" + #include #include +#include +#include static uint16_t calc_crc(uint8_t *data, size_t data_length); @@ -38,6 +40,9 @@ int PL1167_nRF24::recalc_parameters() { // +2 for CRC size_t packet_length = _maxPacketLength + 2; + // resize packetlength for Hamming Code + if(_enableFEC23) packet_length = (packet_length) *1.5; + // Read an extra byte if we don't include the trailer in the syncword if (_syncwordLength < 5) { ++packet_length; @@ -71,6 +76,10 @@ int PL1167_nRF24::setMaxPacketLength(uint8_t maxPacketLength) { return recalc_parameters(); } +void PL1167_nRF24::enableFEC23(bool enable){ + _enableFEC23 = enable; +} + int PL1167_nRF24::receive(uint8_t channel) { if (channel != _channel) { _channel = channel; @@ -152,6 +161,19 @@ int PL1167_nRF24::transmit(uint8_t channel) { } } + if(_enableFEC23) { + #ifdef DEBUG_PRINTF + Serial.printf_P(PSTR("FEC23 enabled (%d bytes)\n"), outp); + #endif + + // New packet length from encoder + outp = _FEC.encodeMessage(tmp, outp); + + #ifdef DEBUG_PRINTF + Serial.printf_P(PSTR("Packet after encode (%d bytes): "), outp); + #endif + } + yield(); _radio.write(tmp, outp); @@ -167,6 +189,18 @@ int PL1167_nRF24::transmit(uint8_t channel) { * Note that because the Trailer is 4 bits, the remaining data is not byte-aligned. * * Bit-order is reversed. + * + * Note: If FEC23 enabled, Data(Length, Packet, CRC) is encoded by Hamming 15,10 + * So the length increased by 50% + * + * When Packetdata length is 7, Packet is 15 Bytes + * 1(len) +7(data) +2(CRC) =10 *1.5 = 15 + * + * + * Data seems like: + * 1234567812PPPPP3456781234PPPPP5678123456PPPPP + * + * This is done BEFORE changing bit-order * */ int PL1167_nRF24::internal_receive() { @@ -200,6 +234,21 @@ int PL1167_nRF24::internal_receive() { // buffer = (buffer << 8) | currentByte; // } + if(_enableFEC23){ + #ifdef DEBUG_PRINTF + Serial.printf_P(PSTR("FEC23 enabled (%d bytes): "), _receive_length); + #endif + + _receive_length = _FEC.decodeMessage(tmp, _receive_length); + #ifdef DEBUG_PRINTF + Serial.printf_P(PSTR("Packet after decode (%d bytes): "), _receive_length); + for (int i = 0; i < outp; i++) { + Serial.printf_P(PSTR("%02X "), tmp[i]); + } + Serial.print(F("\n")); + #endif + } + for (int inp = 0; inp < _receive_length; inp++) { tmp[outp++] = reverseBits(tmp[inp]); } @@ -236,7 +285,7 @@ int PL1167_nRF24::internal_receive() { _received = true; #ifdef DEBUG_PRINTF - Serial.printf_P(PSTR("Successfully parsed packet of length %d\n"), _packet_length); + Serial.printf_P(PSTR("Successfully parsed packet of length %d, chksum %04x\n"), _packet_length, recvCrc); #endif return outp; diff --git a/lib/Radio/PL1167_nRF24.h b/lib/Radio/PL1167_nRF24.h index b38dde78..fd25ebec 100644 --- a/lib/Radio/PL1167_nRF24.h +++ b/lib/Radio/PL1167_nRF24.h @@ -10,6 +10,7 @@ #endif #include "RF24.h" +#include "PL1167_FEC23.h" // #define DEBUG_PRINTF @@ -19,11 +20,14 @@ class PL1167_nRF24 { public: PL1167_nRF24(RF24& radio); + PL1167_FEC23 _FEC; int open(); int setSyncword(const uint8_t syncword[], size_t syncwordLength); int setMaxPacketLength(uint8_t maxPacketLength); + void enableFEC23(bool enable); + int writeFIFO(const uint8_t data[], size_t data_length); int transmit(uint8_t channel); int receive(uint8_t channel); @@ -31,7 +35,7 @@ class PL1167_nRF24 { private: RF24 &_radio; - + const uint8_t* _syncwordBytes = nullptr; uint8_t _syncwordLength = 4; uint8_t _maxPacketLength = 8; @@ -46,6 +50,7 @@ class PL1167_nRF24 { uint8_t _preamble = 0; uint8_t _packet[32]; bool _received = false; + bool _enableFEC23 = false; int recalc_parameters(); int internal_receive(); diff --git a/lib/Settings/Settings.cpp b/lib/Settings/Settings.cpp index 04100395..fb58102d 100644 --- a/lib/Settings/Settings.cpp +++ b/lib/Settings/Settings.cpp @@ -45,6 +45,14 @@ void Settings::updateDeviceIds(JsonArray arr) { } } +void Settings::updateActiveConfigs(JsonArray arr) { + this->activeRadioConfigs.clear(); + + for (size_t i = 0; i < arr.size(); ++i) { + this->activeRadioConfigs.push_back(arr[i]); + } +} + void Settings::updateGatewayConfigs(JsonArray arr) { gatewayConfigs.clear(); @@ -112,6 +120,15 @@ void Settings::patch(JsonObject parsedSettings) { rf24Channels = JsonHelpers::jsonArrToVector(arr, RF24ChannelHelpers::valueFromName); } + if (parsedSettings.containsKey("active_radio_configs")) { + JsonArray arr = parsedSettings["active_radio_configs"]; + updateActiveConfigs(arr); + + for(uint8_t i = 0; i < this->activeRadioConfigs.size(); i++){ + Serial.printf("load id: %d\n", this->activeRadioConfigs[i]); + } + } + if (parsedSettings.containsKey("rf24_listen_channel")) { this->rf24ListenChannel = RF24ChannelHelpers::valueFromName(parsedSettings["rf24_listen_channel"]); } @@ -220,7 +237,21 @@ void Settings::load(Settings& settings) { if (! error) { JsonObject parsedSettings = json.as(); + + // Ensure that there are valid configs before patch + if(!parsedSettings.containsKey("active_radio_configs")){ + // First start use only sidoh's configs + Serial.printf("active_radio_configs not found, creating\n"); + JsonArray configsArr = parsedSettings.createNestedArray("active_radio_configs"); + configsArr.add(0); + configsArr.add(1); + configsArr.add(2); + configsArr.add(3); + configsArr.add(4); + } + settings.patch(parsedSettings); + } else { Serial.print(F("Error parsing saved settings file: ")); Serial.println(error.c_str()); @@ -298,6 +329,15 @@ void Settings::serialize(Print& stream, const bool prettyPrint) { JsonArray channelArr = root.createNestedArray("rf24_channels"); JsonHelpers::vectorToJsonArr(channelArr, rf24Channels, RF24ChannelHelpers::nameFromValue); + JsonArray configsArr = root.createNestedArray("active_radio_configs"); + JsonHelpers::copyFrom(configsArr, this->activeRadioConfigs); + + for(uint8_t i = 0; i < this->activeRadioConfigs.size(); i++){ + Serial.printf("save id: %d\n", this->activeRadioConfigs[i]); + } + + + JsonArray deviceIdsArr = root.createNestedArray("device_ids"); JsonHelpers::copyFrom(deviceIdsArr, this->deviceIds); diff --git a/lib/Settings/Settings.h b/lib/Settings/Settings.h index bb95d386..87ae6d92 100644 --- a/lib/Settings/Settings.h +++ b/lib/Settings/Settings.h @@ -143,6 +143,7 @@ class Settings { String toJson(const bool prettyPrint = true); void serialize(Print& stream, const bool prettyPrint = false); void updateDeviceIds(JsonArray arr); + void updateActiveConfigs(JsonArray arr); void updateGatewayConfigs(JsonArray arr); void patch(JsonObject obj); String mqttServer(); @@ -185,6 +186,7 @@ class Settings { RF24PowerLevel rf24PowerLevel; std::vector deviceIds; std::vector rf24Channels; + std::vector activeRadioConfigs; std::vector groupStateFields; std::vector> gatewayConfigs; RF24Channel rf24ListenChannel; diff --git a/lib/Types/MiLightRemoteType.cpp b/lib/Types/MiLightRemoteType.cpp index 2e08f7c2..f5ccea20 100644 --- a/lib/Types/MiLightRemoteType.cpp +++ b/lib/Types/MiLightRemoteType.cpp @@ -8,6 +8,8 @@ static const char* REMOTE_NAME_FUT089 = "fut089"; static const char* REMOTE_NAME_RGB = "rgb"; static const char* REMOTE_NAME_FUT091 = "fut091"; static const char* REMOTE_NAME_FUT020 = "fut020"; +static const char* REMOTE_NAME_CASALUX = "casalux"; +static const char* REMOTE_NAME_NLG = "nlg"; const MiLightRemoteType MiLightRemoteTypeHelpers::remoteTypeFromString(const String& type) { if (type.equalsIgnoreCase(REMOTE_NAME_RGBW) || type.equalsIgnoreCase("fut096")) { @@ -38,6 +40,14 @@ const MiLightRemoteType MiLightRemoteTypeHelpers::remoteTypeFromString(const Str return REMOTE_TYPE_FUT020; } + if (type.equalsIgnoreCase(REMOTE_NAME_CASALUX)) { + return REMOTE_TYPE_CASALUX; + } + + if (type.equalsIgnoreCase(REMOTE_NAME_NLG)) { + return REMOTE_TYPE_NLG; + } + Serial.print(F("remoteTypeFromString: ERROR - tried to fetch remote config for type: ")); Serial.println(type); @@ -60,6 +70,10 @@ const String MiLightRemoteTypeHelpers::remoteTypeToString(const MiLightRemoteTyp return REMOTE_NAME_FUT091; case REMOTE_TYPE_FUT020: return REMOTE_NAME_FUT020; + case REMOTE_TYPE_CASALUX: + return REMOTE_NAME_CASALUX; + case REMOTE_TYPE_NLG: + return REMOTE_NAME_NLG; default: Serial.print(F("remoteTypeToString: ERROR - tried to fetch remote config name for unknown type: ")); Serial.println(type); diff --git a/lib/Types/MiLightRemoteType.h b/lib/Types/MiLightRemoteType.h index 1b051dd0..80326ed8 100644 --- a/lib/Types/MiLightRemoteType.h +++ b/lib/Types/MiLightRemoteType.h @@ -10,7 +10,9 @@ enum MiLightRemoteType { REMOTE_TYPE_RGB = 3, REMOTE_TYPE_FUT089 = 4, REMOTE_TYPE_FUT091 = 5, - REMOTE_TYPE_FUT020 = 6 + REMOTE_TYPE_FUT020 = 6, + REMOTE_TYPE_CASALUX = 7, + REMOTE_TYPE_NLG = 8 }; class MiLightRemoteTypeHelpers { diff --git a/platformio.ini b/platformio.ini index c2da520d..22ca9388 100644 --- a/platformio.ini +++ b/platformio.ini @@ -26,7 +26,7 @@ lib_deps_external = extra_scripts = pre:.build_web.py test_ignore = remote -upload_speed = 460800 +upload_speed = 256000 build_flags = !python3 .get_version.py # For compatibility with WebSockets 2.1.4 and v2.4 of the Arduino SDK @@ -41,7 +41,6 @@ build_flags = # -D DEBUG_PRINTF # -D MQTT_DEBUG # -D MILIGHT_UDP_DEBUG -# -D STATE_DEBUG [env:nodemcuv2] platform = ${common.platform} diff --git a/web/src/index.html b/web/src/index.html index 0a5c2428..5994ad87 100644 --- a/web/src/index.html +++ b/web/src/index.html @@ -20,7 +20,7 @@ - + @@ -96,7 +96,7 @@
-
+
@@ -160,6 +160,12 @@
  • FUT020
  • +
  • + Casalux +
  • +
  • + NLG(Neuhaus) +
  • @@ -201,7 +207,7 @@
    Saturation
    -
    +
    Color Temperature
    diff --git a/web/src/js/script.js b/web/src/js/script.js index a2bb2bf4..45147d15 100644 --- a/web/src/js/script.js +++ b/web/src/js/script.js @@ -226,6 +226,24 @@ var UI_FIELDS = [ { 'LT8900': 'PL1167/LT8900' }, tab: "tab-radio" + }, { + tag: "active_radio_configs", + friendly: "Active Radio Configs", + help: "More active configs means more channel hopping", + type: "option_buttons", + settings: { + multiple: true, + }, + options: { + '0': 'RGBW', + '1': 'CCT', + '2': 'Fut89, RGB+CCT', + '3': 'RGB', + '4': 'FUT020', + '5': 'Casalux', + '6': 'NLG' + }, + tab: "tab-radio" }, { tag: "rf24_power_level", friendly: "nRF24 Power Level",