////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // SantaSleigh // // // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// #define USE_SERIAL 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Library includes. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include // for the html web server (web page) #include // for MDNS #include // for the socket server (data transmission) #include // for servo drive ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Constants. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Port numbers. #define PORT_HTTP 80 // port number for http #define PORT_WS 2205 // port number for socket // Servo. #define SERVO_OFF 90 // value to stop servo ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Variables. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Servos. Servo ServoLeft; // left servo Servo ServoRight; // right servo // Wifi. // Acccess point ssid. IPAddress IpAddress(192,168,20,20); // access point ip address IPAddress IpGateway(192,168,20,1); // access point gateway IPAddress IpSubnet(255,255,255,0); // access point subnet mask String sSsidSantaSleigh = "SantaSleigh"; // access point ssid // Servers (http and sw). int nX = 50; // servo x int nY = 50; // servo y ESP8266WebServer wsWebServer(PORT_HTTP); // html server WebSocketsServer webSocket = WebSocketsServer(PORT_WS); // socket server // Wifi router password, wifi router ssid and access point ssid. String sPassword = "your_ssid"; // router and access point password String sSsidAccessPoint = "SantaSleigh"; // access point ssid String sSsidRouter = "your_password"; // router ssid ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // SantaSleigh web page (client). // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // The SantaSleigh web page string consists of both Javascript (for touch control, touch control graphics // and data transmission), and html (for the web page). String SantaSleighWebPage= ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Javascript content of web page string. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// "\n" ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // HTML content of web page. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// "\n" "\n" "\n" "SantaSleigh\n" "\n" "\n" "\n" "\n" "\n" "\n" "" ; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // SantaSleigh setup. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// void setup() { // Serial. // // Serial is only necessary for debugging. #if USE_SERIAL Serial.begin(115200); while(!Serial){}; #endif // Wifi. // Set the wifi mode to access point and station mode. WiFi.mode(WIFI_AP_STA); // Set the station mode ssid and password. WiFi.begin(sSsidRouter.c_str(), sPassword.c_str()); // Set the access point ip address, gateway and subnet. WiFi.softAPConfig(IpAddress, IpGateway, IpSubnet); // Set the access point ssid and password. WiFi.softAP(sSsidAccessPoint.c_str(), sPassword.c_str()); // Server. // Root is the webpage. // // "/" is sent from the http client and is a request for a complete webpage refresh. wsWebServer.on("/", []() { wsWebServer.send(200, "text/html", SantaSleighWebPage); }); // Start the server. wsWebServer.begin(); // Start the socket. webSocket.begin(); webSocket.onEvent(SantaSleighSocketEvent); // Add http and ws services to MDNS. // // Notes: // // 1) "http" service is for the html portion of the web page and is serviced on port number PORT_HTTP. // 2) "ws" service is for the javascript socket portion of the web page and is serviced on port nomber PORT_WS. MDNS.begin("SantaSleigh", WiFi.localIP()); MDNS.addService("http", "tcp", PORT_HTTP); MDNS.addService("ws", "tcp", PORT_WS); // Servos. ServoLeft.write(SERVO_OFF); ServoLeft.attach(12); ServoRight.write(SERVO_OFF); ServoRight.attach(13); // Send the ip address to the serial monitor. #if USE_SERIAL Serial.print("SantaSleigh: waiting for wifi connect"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nSantaSleigh: wifi connect with IP Address : " + WiFi.localIP().toString()); #endif } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // SantaSleigh Main loop. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// void loop() { // Update server. wsWebServer.handleClient(); // Update socket. webSocket.loop(); // Give up some time. delay(20); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // SantaSleighSocketEvent // Process socket client events. // Entry : client number // : event type // : pointer to message received from client // : length of message received from client // Returns : nothing // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SantaSleighSocketEvent(unsigned char ClientNumber, WStype_t EventType, unsigned char * Message, unsigned int MessageLength) { // Process event type. switch(EventType) { // Process event type connect. case WStype_CONNECTED: { // Display connected client ip and url. IPAddress ip = webSocket.remoteIP(ClientNumber); #if USE_SERIAL Serial.printf("Client #%u connect :\n", ClientNumber); Serial.printf(" ip address : %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); // Serial.printf(" url : %s\n", Message); #endif // Send a message to client webSocket.sendTXT(ClientNumber, "You are connected."); } break; // Process event type client text. case WStype_TEXT: { // Validate the incoming SantaSleigh data string by checking the first 5 characters for "zpllc". if((Message[0] == 'z') && (Message[1] == 'p') && (Message[2] == 'l') && (Message[3] == 'l') && (Message[4] == 'c')) { // Valid SantaSleigh header, convert incoming SantaSleigh data string to x and y. // Convert the string to double. double data = strtod((const char *) & Message[5], NULL); // Derive and limit the x component. nX = (int)data / 100; nX = (nX > 0) ? (nX < 99) ? nX : 99 : 0; // Derive and limit the y component. nY = (int)data % 100; nY = (nY > 0) ? (nY < 99) ? nY : 99 : 0; // Set the servo values based on the x and y components. int nServoLeftScale = (((nX < 50) ? nX : 50) * 100) / 50; int nServoRightScale = (((nX > 50) ? (100 - nX) : 50) * 100) / 50; ServoLeft.write(SERVO_OFF + ((nServoLeftScale * (nY - 50)) / 100)); ServoRight.write(SERVO_OFF - ((nServoRightScale * (nY - 50)) / 100)); // Send x and y components to the serial monitor. #if USE_SERIAL Serial.printf("Client #%u sent: x = %02d, y = %02d\n", ClientNumber, nX, nY); #endif } else { // Invalid SantaSleigh header, send data to serial monitor. #if USE_SERIAL Serial.printf("Client #%u invalid data: %s\n", ClientNumber, Message); #endif } } break; // Process event type disconnect. case WStype_DISCONNECTED: { // Process client disconnect. #if USE_SERIAL Serial.printf("Client #%u disconnected.\n", ClientNumber); #endif } break; } }