tested.. various idea for dev.

but we won't do that in the end.
This commit is contained in:
doohoyi 2019-12-07 23:45:52 +09:00
parent 6483befe7d
commit 14a39eda33
4 changed files with 427 additions and 2 deletions

View file

@ -1,5 +1,99 @@
# crickets - wireless mesh sound device
## platformio
## esp8266 or esp32 based WMN
## small IoT objects in the wireless mesh network
## (optional) teensy35/36 or arduino nano.. by i2c comm.
### some cricket use only espX.. + motor or relay etc..
espX 단계에서는.. json으로 대화를 한다.
어차피 painlessmesh 도 그렇고. 문자열기반이므로, 이부분 어렵지 않음.
나중에 어떤 espX 한대가 중계기가 되는 경우 브라우져의 js 에 연결도 스무쓰해서 좋다.
그런데, teensy 가 있는 경우에는..
즉, sampler 인 경우에는.. 뭔가 컨트롤이 오고 갈 필요가 있는데..
이 컨트롤은 지금까지.. i2c를 써왔었는데.
i2c는 커멘드의 구조를 매번 잡아야하고 이런저런 것들이 불편하다.
좀더 유연한 통신을 원하는 것 같기도 하다. 양방향시리얼통신이라던가.. (uart)
또한, 지금 UI를 짜는 경우에.. 즉 브라우져 말고.. 디스플레이중심장치말고. 좀더 연주중심장치를 인터페이스 그니까, 오르가넬레 / pd 연결하는 경우에
osc 가 가장 유력한데
그런경우에 어떤 espX 는 osc를 보내주면 좋겠다.. 라는 바램이 있긴하다.
serialize가 된다면 어떤 메세지던 상관없다 매쉬입장에서는..
그렇다면, 애초에.. json을 하지 말고. osc를 주고 받게 할 수도 있지 않을까? espX 단부터..
브라우져도 osc.js 가 있기때문에 인터페이스할수있고..
이렇게 되면 teensy도 CNMAT OSC 가 있고.. espX 도 같은 라이브러리가 서포트 하는 걸로 보이는데..
다만, OSCBundle을 serialize 할 수 있는 수단. 그리고, 성능적인 오버헤드가 어느정도인지.. 그런질문이 남는다.
OSCBundle은 SLIP으로 encoding 하게 되어있는데..그렇게 하면 몬가 좋은게 있겠나? ..
암튼 근데 그게.. serial 통신 기반으로 하게 되어있어서.. espX <-> teensy 사이에는 쓸수있겠지만.. espX mesh 안에서는 string 메세지로 통신하니까. 쓰기가 애매하다. 별도로 print 하는 방법으로 하면 좋겠지만.. printout을 할수 있게 되어있는지 잘 모르겠음. 불확실.
teensy 또는 espX <-> pc 사이에는 쓸수가 있고, 썼을때, 유용하다. osc 니까.
문제는 mesh 이후인데.. mesh가 웹서비스를 할경우에.. osc.js로 할수가 있겠지만.. 음..
한가지 어서 정하는게 좋을거 같은데....
mesh들 끼리 통신은 string 이다.
osc를 string으로 표현하면 딱 좋아.
osc를 slip으로 encoding 한다고 하는 것은 packet을 만든다는 건데..
사실 그럴필요도 없지 않나 싶다.
그냥 다 전개된 string으로 만드는 방법만 있다면, 모든 것이 osc 가 될수가 있는데.
그런 방법이 있으면 좋겠지만.....
그냥 지금 가능한 방법으로만 한다면..
json이 serialize가 되니까.. osc를 json으로 바꿔서 serialize해서 보내고 받고 하는 것이 한가지 방법.
osc 는 되게 쌈빡한 메세지인데.. 이걸 json으로 만들면.. 되게 지저분해진다. overhead가 많아. 간단하게 적으면 되는 건데.. 그냥 프린트하는 방법이 없을까? cnmat osc 에서.... 한번 조사해보자.
----
StringStream 이란걸 구해다가 중간에 변환기 처럼 사용해서, 테스트를 해봤는데... 변환은 되지만, mesh에 전송했을때 안가는 문제가 있었는데, 원인은 다음과 같다.
https://gitlab.com/painlessMesh/painlessMesh/issues/140
painlessmesh 에서.. 그냥 binary data를 보내는 걸 허용을 안하기때문에.. osc 메세지를 바로 보낼수가 없다.
base64 인코딩을 해야한다는데.. 그렇게 되면, integrity가 깨진다고나 할까.. (숫자들만 base64 를 할건지.. 전체다 할건지.. 암튼 지저분해지잖아.)
어차피 내부적으로 json을 이미 쓰고 있다는 걸까? .. 그런가보다..
그럼 그냥 json으로 번역하도록 하는게 맞는 걸까?..
그럼 이걸.. generally 할 수 있어야 할텐데..
osc --> json json --> osc 자동..
그런걸 만들 수 있을까?
OSCBundle 이란게 있다면. 이거를 확장해서 ArduinoJson 으로 print 하게 만들수도 있을까..
아.. 쩝. 지저분하거나, 혹은 어렵네..
가능하긴 한데.. 어려움.. 흠. 그래서 좀 귀찮음..
----
그렇다면..
아예.. 모든것을 json으로 바꿀순 없을까?
예를들어서 pd만 특별하게 예외로 한다던가 하고...
https://github.com/residuum/PuRestJson/wiki/%5Bjson-decode%5D-And-%5Bjson-encode%5D:-JSON-Data-in-Pd
이런게 있는데.. 흥미롭긴하지만.. symbol 로 json string을 받아야하는데 comport로 받으니까 (ArduinoJson) 그렇게 안됨.. serial 통신이니까. slip encoding이라도 안하면.. event도 아니고.. packet이면 차라리 편한데...
----
결국 중간에 json <--> osc 변환을 하는게 가장 현명한 방법인데.. 이걸 generally 구현하려면, 좀 짜증날거 같고..
그냥 약식으로 해야 할거 같네.. 어차피.. 이게 .. json이든 머든.. 형식이 free하다고 해도 마냥 free하게 쓸수있는 것도 아님.
----
또는....... ESP-MESH 를 사용해서 전체적으로 다시 만드는 수가 있음. 즉, painlessmesh 를 버리는 거지.
ESP-MESH 에서는 binary 를 보낼수가 있음.
즉, OSCBundle 을 StringStream으로 담아서.. 보내고 받고 할 수 있음.
그러면.. 되나?
그러면.. 모든 곳에서 OSC 메세지를 사용할수가 있게 되나?
----
근데. 솔직히.. 그거는 좀.. 너무 큰 일이다. 지금도 시간 많이 썼는데.. 더 이상은 위험하게 하고 싶지 않고, 재미없어질듯.
하지만, 다음에 꼭 해보자...
장기적으로 보나.. 필요한 방향..

View file

@ -0,0 +1,25 @@
#ifndef _STRING_STREAM_H_
#define _STRING_STREAM_H_
#include <Stream.h>
class StringStream : public Stream
{
public:
StringStream(String &s) : string(s), position(0) { }
// Stream methods
virtual int available() { return string.length() - position; }
virtual int read() { return position < string.length() ? string[position++] : -1; }
virtual int peek() { return position < string.length() ? string[position] : -1; }
virtual void flush() { };
// Print methods
virtual size_t write(uint8_t c) { string += (char)c; return 1;};
private:
String &string;
unsigned int length;
unsigned int position;
};
#endif // _STRING_STREAM_H_

View file

@ -17,8 +17,10 @@ framework = arduino
platform = espressif8266
board = nodemcuv2
framework = arduino
upload_speed = 921600
[env:huzzah]
platform = espressif8266
board = huzzah
framework = arduino
upload_speed = 921600

304
src/main.cpp Normal file
View file

@ -0,0 +1,304 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to generate a JSON document with ArduinoJson.
//
// https://arduinojson.org/v6/example/generator/
#include <Arduino.h>
#include <ArduinoJson.h>
void setup() {
// Initialize Serial port
Serial.begin(9600);
// while (!Serial) continue;
}
void loop() {
// not used in this example
StaticJsonDocument<200> doc;
doc["sensor"] = "gps";
doc["time"] = 1351824120;
JsonArray data = doc.createNestedArray("data");
data.add(48.756080);
data.add(2.302038);
serializeJson(doc, Serial);
Serial.println();
// serializeJsonPretty(doc, Serial);
delay(1000);
}
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
//
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
// It begins with a simple example, like the one above, and then adds more
// features like serializing directly to a file or an HTTP request.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
// //************************************************************
// // this is a simple example that uses the easyMesh library
// //
// // 1. blinks led once for every node on the mesh
// // 2. blink cycle repeats every BLINK_PERIOD
// // 3. sends a silly message to every node on the mesh at a random time between 1 and 5 seconds
// // 4. prints anything it receives to Serial.print
// //
// //
// //************************************************************
// #include <Arduino.h>
// #include <painlessMesh.h>
//
// #include <OSCBundle.h>
// #include <OSCBoards.h>
// #include "StringStream.h"
//
// // some gpio pin that is connected to an LED...
// // on my rig, this is 5, change to the right number of your LED.
// #define LED 2 // GPIO number of connected LED, ON ESP-12 IS GPIO2
//
// #define BLINK_PERIOD 3000 // milliseconds until cycle repeat
// #define BLINK_DURATION 100 // milliseconds LED is on for
//
// #define MESH_SSID "whateverYouLike"
// #define MESH_PASSWORD "somethingSneaky"
// #define MESH_PORT 5555
//
// // Prototypes
// void sendMessage();
// void receivedCallback(uint32_t from, String & msg);
// void newConnectionCallback(uint32_t nodeId);
// void changedConnectionCallback();
// void nodeTimeAdjustedCallback(int32_t offset);
// void delayReceivedCallback(uint32_t from, int32_t delay);
//
// Scheduler userScheduler; // to control your personal task
// painlessMesh mesh;
//
// bool calc_delay = false;
// SimpleList<uint32_t> nodes;
//
// void sendMessage(); // Prototype
// Task taskSendMessage( TASK_SECOND * 1, TASK_FOREVER, &sendMessage ); // start with a one second interval
//
// // Task to blink the number of nodes
// Task blinkNoNodes;
// bool onFlag = false;
//
// void setup() {
// Serial.begin(115200);
//
// pinMode(LED, OUTPUT);
//
// mesh.setDebugMsgTypes(ERROR | DEBUG); // set before init() so that you can see error messages
// // mesh.setDebugMsgTypes(ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE); // set before init() so that you can see error messages
//
// mesh.init(MESH_SSID, MESH_PASSWORD, &userScheduler, MESH_PORT);
// mesh.onReceive(&receivedCallback);
// mesh.onNewConnection(&newConnectionCallback);
// mesh.onChangedConnections(&changedConnectionCallback);
// mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
// mesh.onNodeDelayReceived(&delayReceivedCallback);
//
// userScheduler.addTask( taskSendMessage );
// taskSendMessage.enable();
//
// blinkNoNodes.set(BLINK_PERIOD, (mesh.getNodeList().size() + 1) * 2, []() {
// // If on, switch off, else switch on
// if (onFlag)
// onFlag = false;
// else
// onFlag = true;
// blinkNoNodes.delay(BLINK_DURATION);
//
// if (blinkNoNodes.isLastIteration()) {
// // Finished blinking. Reset task for next run
// // blink number of nodes (including this node) times
// blinkNoNodes.setIterations((mesh.getNodeList().size() + 1) * 2);
// // Calculate delay based on current mesh time and BLINK_PERIOD
// // This results in blinks between nodes being synced
// blinkNoNodes.enableDelayed(BLINK_PERIOD -
// (mesh.getNodeTime() % (BLINK_PERIOD*1000))/1000);
// }
// });
// userScheduler.addTask(blinkNoNodes);
// blinkNoNodes.enable();
//
// randomSeed(analogRead(A0));
// }
//
// void loop() {
// mesh.update();
// digitalWrite(LED, !onFlag);
// }
//
// OSCErrorCode error;
// void oscRecvNodeId(OSCMessage &msg) {
// Serial.print("/nodeid --> ");
// Serial.println(msg.getInt(0));
// }
//
// void oscRecvMyFreeMemory(OSCMessage &msg) {
// Serial.print("/myFreeMemory --> ");
// Serial.println(msg.getInt(0));
// }
//
//
// void sendMessage() {
// //
// OSCBundle bndl;
// String oscmsg;
// StringStream sstream(oscmsg);
// bndl.add("/nodeid").add(mesh.getNodeId());
// bndl.add("/myFreeMemory").add(ESP.getFreeHeap());
// bndl.send(sstream);
// //
// mesh.sendBroadcast(oscmsg);
//
// //
// int size = sstream.available();
// //
// OSCBundle bndl2;
// if (size > 0) {
// while (size--) {
// bndl2.fill(sstream.read());
// }
// if (!bndl2.hasError()) {
// Serial.println("bndl2.dispatch...");
// bndl2.dispatch("/nodeid", oscRecvNodeId);
// bndl2.dispatch("/myFreeMemory", oscRecvMyFreeMemory);
// } else {
// error = bndl2.getError();
// Serial.print("error: ");
// Serial.println(error);
// }
// }
//
//
// if (calc_delay) {
// SimpleList<uint32_t>::iterator node = nodes.begin();
// while (node != nodes.end()) {
// mesh.startDelayMeas(*node);
// node++;
// }
// calc_delay = false;
// }
//
// Serial.print("Sending message: ");
// Serial.println(oscmsg);
//
// taskSendMessage.setInterval( random(TASK_SECOND * 1, TASK_SECOND * 5)); // between 1 and 5 seconds
// }
//
// void receivedCallback(uint32_t from, String & msg) {
// Serial.printf("startHere: Received from %u msg=", from);
// Serial.println(msg);
// //
// OSCBundle bndl;
// String oscmsg;
// StringStream sstream(oscmsg);
// oscmsg = msg;
// int size = sstream.available();
// //
// if (size > 0) {
// while (size--) {
// bndl.fill(sstream.read());
// }
// if (!bndl.hasError()) {
// Serial.println("bndl.dispatch...");
// bndl.dispatch("/nodeid", oscRecvNodeId);
// bndl.dispatch("/myFreeMemory", oscRecvMyFreeMemory);
// } else {
// error = bndl.getError();
// Serial.print("error: ");
// Serial.println(error);
// }
// }
// }
//
// void newConnectionCallback(uint32_t nodeId) {
// // Reset blink task
// onFlag = false;
// blinkNoNodes.setIterations((mesh.getNodeList().size() + 1) * 2);
// blinkNoNodes.enableDelayed(BLINK_PERIOD - (mesh.getNodeTime() % (BLINK_PERIOD*1000))/1000);
//
// Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
// Serial.printf("--> startHere: New Connection, %s\n", mesh.subConnectionJson(true).c_str());
// }
//
// void changedConnectionCallback() {
// Serial.printf("Changed connections\n");
// // Reset blink task
// onFlag = false;
// blinkNoNodes.setIterations((mesh.getNodeList().size() + 1) * 2);
// blinkNoNodes.enableDelayed(BLINK_PERIOD - (mesh.getNodeTime() % (BLINK_PERIOD*1000))/1000);
//
// nodes = mesh.getNodeList();
//
// Serial.printf("Num nodes: %d\n", nodes.size());
// Serial.printf("Connection list:");
//
// SimpleList<uint32_t>::iterator node = nodes.begin();
// while (node != nodes.end()) {
// Serial.printf(" %u", *node);
// node++;
// }
// Serial.println();
// calc_delay = true;
// }
//
// void nodeTimeAdjustedCallback(int32_t offset) {
// Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(), offset);
// }
//
// void delayReceivedCallback(uint32_t from, int32_t delay) {
// Serial.printf("Delay to node %u is %d us\n", from, delay);
// }
//
// // #include <Arduino.h>
// //
// // #include <OSCBundle.h>
// // #include <OSCBoards.h>
// //
// // #include "StringStream.h"
// //
// // void setup() {
// // Serial.begin(9600);
// // }
// //
// // void loop(){
// // OSCBundle bndl;
// // int size;
// // //receive a bundle
// //
// // while(!SLIPSerial.endofPacket())
// // if( (size = SLIPSerial.available()) > 0)
// // {
// // while(size--)
// // bndl.fill(SLIPSerial.read());
// // }
// //
// // // if(!bndl.hasError())
// // // {
// // static int32_t sequencenumber=0;
// // // we can sneak an addition onto the end of the bundle
// // // bndl.add("/micros").add((int32_t)micros()); // (int32_t) is the type of OSC Integers
// // bndl.add("/sequencenumber").add(sequencenumber++);
// // bndl.add("/digital/5").add(digitalRead(5)==HIGH);
// // // bndl.add("/lsb").add((sequencenumber &1)==1);
// // String sstr;
// // StringStream ss(sstr);
// // bndl.send(ss);
// // Serial.println(sstr);
// // // }
// //
// // delay(1000);
// // }