// // wirelessly connected cloud (based on a LPWAN, called ESP-NOW) // // // puredata gathering @ ururu.cloud, Seoul // // // 2024 02 17 // // this module will be an esp-now node in a group. // like, a bird in a group of birds. // // esp-now @ esp8266 w/ broadcast address (FF:FF:FF:FF:FF:FF) // always broadcasting. everyone is 'talkative'. // //======================== #define MY_GROUP_ID (0) #define MY_ID (MY_GROUP_ID + 2) #define MY_SIGN ("POSTMAN|OSC(Pd)") //======================== //======================== #define WIFI_CHANNEL 1 //======================= //======================== // // MONITORING_ACTIVE // : activate serial communication monitoring @ TX1, if defined. // since 'Serial' is occupied by 'SLIPSerial', // alternativly 'Serial1' will send out messages. // // 'Serial1' - D4/GPIO2/TDX1 @ nodemcu (this is TX only.) // //======================== // #define MONITORING_ACTIVE //arduino #include //message types #include "message.h" //espnow #include #include //task #include Scheduler runner; //osc #include #include SLIPEncodedSerial SLIPSerial(Serial); void swap_println(String abc) { Serial.flush(); Serial.swap(); Serial.println(abc); Serial.flush(); Serial.swap(); } //-*-*-*-*-*-*-*-*-*-*-*-*- //task #1 : osc processing void route_note(OSCMessage& msg, int offset) { //swap_println("got route_note!"); // matches will happen in the order. that the bundle is packed. static Note note; // (1) --> /onoff if (msg.fullMatch("/onoff", offset)) { // note.clear(); // note.onoff = msg.getFloat(0); // if (note.onoff != 0) note.onoff = 1; } // (2) --> /velocity if (msg.fullMatch("/velocity", offset)) { note.velocity = msg.getFloat(0); } // (3) --> /pitch if (msg.fullMatch("/pitch", offset)) { note.pitch = msg.getFloat(0); } // (4) --> /id if (msg.fullMatch("/id", offset)) { note.id = msg.getInt(0); } // (5) --> /x if (msg.fullMatch("/x", offset)) { note.x1 = msg.getFloat(0); note.x2 = msg.getFloat(1); note.x3 = msg.getFloat(2); note.x4 = msg.getFloat(3); note.ps = msg.getFloat(4); // uint8_t frm_size = sizeof(Note) + 2; uint8_t frm[frm_size]; frm[0] = '['; memcpy(frm + 1, (uint8_t *) ¬e, sizeof(Note)); frm[frm_size - 1] = ']'; // esp_now_send(NULL, frm, frm_size); // to all peers in the list. // #if defined(MONITORING_ACTIVE) Serial1.write(frm, frm_size); Serial1.println(" ==(esp_now_send/0)==> "); #endif // } } extern Task osc_task; void osc() { //osc OSCBundle bundleIN; int size; if (SLIPSerial.available()) { while(!SLIPSerial.endofPacket()) { if( (size = SLIPSerial.available()) > 0) { while(size--) { bundleIN.fill(SLIPSerial.read()); } } } if(!bundleIN.hasError()) { // on '/note' bundleIN.route("/note", route_note); } } } Task osc_task(0, TASK_FOREVER, &osc, &runner, true); // -> ENABLED, at start-up. //*-*-*-*-*-*-*-*-*-*-*-*-* //task #0 : blink led #define LED_PERIOD (11111) #define LED_ONTIME (1) #define LED_GAPTIME (222) #define LED_PIN 2 extern Task blink_task; void blink() { // static int count = 0; count++; // switch (count % 4) { case 0: digitalWrite(LED_PIN, LOW); // first ON blink_task.delay(LED_ONTIME); break; case 1: digitalWrite(LED_PIN, HIGH); // first OFF blink_task.delay(LED_GAPTIME); break; case 2: digitalWrite(LED_PIN, LOW); // second ON blink_task.delay(LED_ONTIME); break; case 3: digitalWrite(LED_PIN, HIGH); // second OFF blink_task.delay(LED_PERIOD - 2* LED_ONTIME - LED_GAPTIME); break; } } Task blink_task(0, TASK_FOREVER, &blink, &runner, true); // -> ENABLED, at start-up. // on 'receive' void onDataReceive(uint8_t * mac, uint8_t *incomingData, uint8_t len) { #if defined(MONITORING_ACTIVE) Serial1.write(incomingData, len); #endif // open => identify => use. if (incomingData[0] == '{' && incomingData[len - 1] == '}' && len == (sizeof(Hello) + 2)) { Hello hello(""); memcpy((uint8_t *) &hello, incomingData + 1, sizeof(Hello)); // #if defined(MONITORING_ACTIVE) Serial1.println(hello.to_string()); #endif // OSCMessage osc("/hello"); osc.add(hello.id); osc.add(hello.h1); osc.add(hello.h2); osc.add(hello.h3); osc.add(hello.h4); // SLIPSerial.beginPacket(); osc.send(SLIPSerial); SLIPSerial.endPacket(); osc.empty(); // } // open => identify => use. if (incomingData[0] == '[' && incomingData[len - 1] == ']' && len == (sizeof(Note) + 2)) { Note note; memcpy((uint8_t *) ¬e, incomingData + 1, sizeof(Note)); // #if defined(MONITORING_ACTIVE) Serial1.println(note.to_string()); #endif } } // on 'sent' void onDataSent(uint8_t *mac, uint8_t sendStatus) { char buff[256] = ""; sprintf(buff, "Delivery failed! -> %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); if (sendStatus != 0) Serial.println(buff); } // void setup() { //led pinMode(LED_PIN, OUTPUT); //serial Serial.begin(57600); delay(100); //info Serial.println(); Serial.println(); Serial.println("\"hi, i m your postman.\""); Serial.println("-"); Serial.println("- my id: " + String(MY_ID) + ", gid: " + String(MY_GROUP_ID) + ", call me ==> \"" + String(MY_SIGN) + "\""); Serial.println("- mac address: " + WiFi.macAddress() + ", channel: " + String(WIFI_CHANNEL)); Serial.println("-"); //wifi - disabled system_phy_set_max_tpw(0); WiFiMode_t node_type = WIFI_STA; WiFi.mode(node_type); //esp-now if (esp_now_init() != 0) { Serial.println("Error initializing ESP-NOW"); return; } esp_now_set_self_role(ESP_NOW_ROLE_COMBO); esp_now_register_send_cb(onDataSent); esp_now_register_recv_cb(onDataReceive); // Serial.println("- ! (esp_now_add_peer) ==> add a 'broadcast peer' (FF:FF:FF:FF:FF:FF)."); uint8_t broadcastmac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; esp_now_add_peer(broadcastmac, ESP_NOW_ROLE_COMBO, 1, NULL, 0); Serial.println("-"); Serial.println("\".-.-.-. :)\""); Serial.println(); // a proper say goodbye. Serial.println("\"bye, this 'Serial' will be occupied by SLIPSerial. find me @ Serial1 (TX only)\""); Serial.println("-"); Serial.println("\".-.-.-. :)\""); delay(1000); // flush out unsent serial messages. // start SLIPSerial on Serial SLIPSerial.begin(57600); // start Serial1 as an alternative #if defined(MONITORING_ACTIVE) Serial1.begin(115200); #endif // clear out any leftover debris. (this will let LED blinking works from initialization.) while(SLIPSerial.available() > 0) { SLIPSerial.read(); } } void loop() { // runner.execute(); // }