feat(stdlib): add xod-dev/esp8266-mcu library

Part of #1454
This commit is contained in:
Evgeny Kochetkov
2018-09-27 19:25:46 +03:00
parent d3dc356775
commit 658ebeeb12
25 changed files with 2310 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
struct State {
};
// clang-format off
{{ GENERATED_CODE }}
// clang-format on
void evaluate(Context ctx) {
if (!isInputDirty<input_CLS>(ctx))
return;
auto client = getValue<input_SOCK>(ctx);
client->stop();
emitValue<output_DONE>(ctx, 1);
}

View File

@@ -0,0 +1,43 @@
{
"description": "Closes an open TCP connection",
"nodes": [
{
"id": "B1MPz-TvKX",
"position": {
"x": -1,
"y": 100
},
"type": "xod/patch-nodes/not-implemented-in-xod"
},
{
"description": "Pulses when the connection is closed",
"id": "ByPfZaPKQ",
"label": "DONE",
"position": {
"x": 0,
"y": 203
},
"type": "xod/patch-nodes/output-pulse"
},
{
"description": "A socket",
"id": "SJiGWTPKm",
"label": "SOCK",
"position": {
"x": 0,
"y": 0
},
"type": "@/input-socket"
},
{
"description": "Close the connection",
"id": "r1eDMb6vKm",
"label": "CLS",
"position": {
"x": 68,
"y": -1
},
"type": "xod/patch-nodes/input-pulse"
}
]
}

View File

@@ -0,0 +1,61 @@
// clang-format off
{{#global}}
#include <ESP8266WiFi.h>
{{/global}}
// clang-format on
const uint8_t TOTAL_RECHECKS = 200;
const uint8_t RECEHCK_DURATION_MS = 30;
struct State {
uint8_t rechecksLeft = TOTAL_RECHECKS;
};
// clang-format off
{{ GENERATED_CODE }}
// clang-format on
void evaluate(Context ctx) {
auto device = getValue<input_DEV>(ctx);
auto state = getState(ctx);
if (isInputDirty<input_CONN>(ctx)) {
auto ssid = getValue<input_SSID>(ctx);
auto ssidLength = length(ssid);
char _ssid[ssidLength + 1];
dump(ssid, _ssid);
_ssid[ssidLength] = '\0';
auto password = getValue<input_PWD>(ctx);
auto passwordLength = length(password);
char _password[passwordLength + 1];
dump(password, _password);
_password[passwordLength] = '\0';
/* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default,
would try to act as both a client and an access-point and could cause
network-issues with your other WiFi-devices on your WiFi-network. */
device->mode(WIFI_STA);
device->begin(_ssid, _password);
state->rechecksLeft = TOTAL_RECHECKS;
setTimeout(ctx, RECEHCK_DURATION_MS);
}
if (isTimedOut(ctx)) {
if (device->status() != WL_CONNECTED) {
state->rechecksLeft -= 1;
if (state->rechecksLeft == 0) {
emitValue<output_ERR>(ctx, 1);
} else {
setTimeout(ctx, RECEHCK_DURATION_MS);
}
} else {
emitValue<output_DONE>(ctx, true);
// DEV and INET are both actually just a pointer to WiFi from ESP8266WiFi.h
emitValue<output_INET>(ctx, (ValueType<output_INET>::T)device);
}
}
}

View File

@@ -0,0 +1,86 @@
{
"description": "Connect to a WiFi network with a given SSID and password",
"nodes": [
{
"id": "BJxASTtLYm",
"position": {
"x": -1,
"y": 101
},
"type": "xod/patch-nodes/not-implemented-in-xod"
},
{
"description": "An internet connection",
"id": "H1Gd15UFQ",
"label": "INET",
"position": {
"x": 0,
"y": 204
},
"type": "@/output-esp8266-mcu-inet"
},
{
"description": "Wi-Fi network password",
"id": "H1z0HpF8Km",
"label": "PWD",
"position": {
"x": 68,
"y": 0
},
"type": "xod/patch-nodes/input-string"
},
{
"description": "Pulses if the connection failed\n",
"id": "HJ7RrpFUY7",
"label": "ERR",
"position": {
"x": 68,
"y": 204
},
"type": "xod/patch-nodes/output-pulse"
},
{
"description": "Name of the Wi-Fi network",
"id": "HJZCrpKLYX",
"label": "SSID",
"position": {
"x": 34,
"y": 0
},
"type": "xod/patch-nodes/input-string"
},
{
"description": "Pulses on a successful connection\n",
"id": "HyLAraK8Km",
"label": "DONE",
"position": {
"x": 34,
"y": 204
},
"type": "xod/patch-nodes/output-pulse"
},
{
"description": "An ESP8266-based MCU",
"id": "HyOPzjUK7",
"label": "DEV",
"position": {
"x": 0,
"y": 0
},
"type": "@/input-esp8266-mcu-device"
},
{
"boundLiterals": {
"__out__": "On Boot"
},
"description": "Establish the connection",
"id": "ryRHTFItQ",
"label": "CONN",
"position": {
"x": 102,
"y": 0
},
"type": "xod/patch-nodes/input-pulse"
}
]
}

View File

@@ -0,0 +1,19 @@
// clang-format off
{{#global}}
#include <ESP8266WiFi.h>
{{/global}}
// clang-format on
struct State {
};
using Type = ESP8266WiFiClass*;
// clang-format off
{{ GENERATED_CODE }}
// clang-format on
void evaluate(Context ctx) {
emitValue<output_OUT>(ctx, &WiFi);
}

View File

@@ -0,0 +1,21 @@
{
"description": "Represents an ESP8266-based MCU",
"nodes": [
{
"id": "B1xU-WjUFX",
"position": {
"x": -1,
"y": -1
},
"type": "xod/patch-nodes/not-implemented-in-xod"
},
{
"id": "HkUZ-iLYm",
"position": {
"x": -1,
"y": 101
},
"type": "xod/patch-nodes/output-self"
}
]
}

View File

@@ -0,0 +1,19 @@
// clang-format off
{{#global}}
#include <ESP8266WiFi.h>
{{/global}}
// clang-format on
struct State {
};
using Type = ESP8266WiFiClass*;
// clang-format off
{{ GENERATED_CODE }}
// clang-format on
void evaluate(Context ctx) {
emitValue<output_OUT>(ctx, &WiFi);
}

View File

@@ -0,0 +1,29 @@
{
"description": "Represents an internet connection",
"nodes": [
{
"id": "By7tuY8YX",
"position": {
"x": 102,
"y": 102
},
"type": "xod/patch-nodes/utility"
},
{
"id": "SyJt_KUF7",
"position": {
"x": 34,
"y": 102
},
"type": "xod/patch-nodes/not-implemented-in-xod"
},
{
"id": "SyqdOtLYX",
"position": {
"x": 34,
"y": 204
},
"type": "xod/patch-nodes/output-self"
}
]
}

View File

@@ -0,0 +1,421 @@
{
"comments": [
{
"content": "If request succeeds, request fresh value after 1 second\nIf request fails, retry after 5 seconds",
"id": "BJnIU4Kt7",
"position": {
"x": 476,
"y": 510
},
"size": {
"height": 51,
"width": 408
}
},
{
"content": "⚠️ Make sure to specify SSID and password of your WiFi network",
"id": "H1hkLF9Fm",
"position": {
"x": 272,
"y": 0
},
"size": {
"height": 51,
"width": 272
}
},
{
"content": "tip: use `https://dweet.io/dweet/for/xod-esp8266-iot?lum=100` to put desired values\n",
"id": "SkhZRSUVFY7",
"position": {
"x": 544,
"y": 408
},
"size": {
"height": 51,
"width": 442
}
}
],
"links": [
{
"id": "B1NbRrIEFFm",
"input": {
"nodeId": "BJCSI4tYQ",
"pinKey": "B18iIoA-m"
},
"output": {
"nodeId": "Hk6RBINtYX",
"pinKey": "Hku0ArhDYX"
}
},
{
"id": "B1cW0HI4YtQ",
"input": {
"nodeId": "BJCSI4tYQ",
"pinKey": "rklUo8jA-Q"
},
"output": {
"nodeId": "Hk6RBINtYX",
"pinKey": "r1E0RH3vYQ"
}
},
{
"id": "BJwbCrI4FtQ",
"input": {
"nodeId": "Byj0rUNKKQ",
"pinKey": "ryv7IRdSP1b"
},
"output": {
"nodeId": "ryJlRBU4FYQ",
"pinKey": "HyLAraK8Km"
}
},
{
"id": "BkSeRHLVKtX",
"input": {
"nodeId": "BJCSI4tYQ",
"pinKey": "BJhHwoRb7"
},
"output": {
"nodeId": "B19RHUNYt7",
"pinKey": "__out__"
}
},
{
"id": "ByLx0SIVYtQ",
"input": {
"nodeId": "Hk6RBINtYX",
"pinKey": "S1Tl8hwFQ"
},
"output": {
"nodeId": "ryJlRBU4FYQ",
"pinKey": "H1Gd15UFQ"
}
},
{
"id": "ByVxABIVtK7",
"input": {
"nodeId": "rkWAH8EYtQ",
"pinKey": "SkW3wouIeQ"
},
"output": {
"nodeId": "HydRr8NttQ",
"pinKey": "BksptX0b7"
}
},
{
"id": "ByXvONKY7",
"input": {
"nodeId": "r1F8u4ttm",
"pinKey": "HJjEe1lnb"
},
"output": {
"nodeId": "HydRr8NttQ",
"pinKey": "Sk6oKXA-Q"
}
},
{
"id": "Bya29sy5Q",
"input": {
"nodeId": "H1BCFNKKm",
"pinKey": "__in__"
},
"output": {
"nodeId": "rkv29jyc7",
"pinKey": "HJhXDIY9-"
}
},
{
"id": "H1Lw_NtYm",
"input": {
"nodeId": "rkWAH8EYtQ",
"pinKey": "HyYh1a3LZ"
},
"output": {
"nodeId": "r1F8u4ttm",
"pinKey": "rJFmgJehW"
}
},
{
"id": "Hk7lASLEKtm",
"input": {
"nodeId": "Byj0rUNKKQ",
"pinKey": "ByU7LRuSPkW"
},
"output": {
"nodeId": "rkMCr8EtYX",
"pinKey": "__out__"
}
},
{
"id": "HkYgCH8NFKX",
"input": {
"nodeId": "HydRr8NttQ",
"pinKey": "rJ55KmC-X"
},
"output": {
"nodeId": "BJCSI4tYQ",
"pinKey": "SkSGwoAZQ"
}
},
{
"id": "Hy5e0SIEKYX",
"input": {
"nodeId": "HydRr8NttQ",
"pinKey": "Sy1it7R-m"
},
"output": {
"nodeId": "BJCSI4tYQ",
"pinKey": "SkYZwiRbm"
}
},
{
"id": "Hyh3csycm",
"input": {
"nodeId": "rkv29jyc7",
"pinKey": "BJI7P8t9Z"
},
"output": {
"nodeId": "SyFdPQqtQ",
"pinKey": "ByHmL0uHPk-"
}
},
{
"id": "SkMjwQqtQ",
"input": {
"nodeId": "SyFdPQqtQ",
"pinKey": "ryv7IRdSP1b"
},
"output": {
"nodeId": "SyETcEtKm",
"pinKey": "Bk4gU0drwJ-"
}
},
{
"id": "SksWAS8VtKQ",
"input": {
"nodeId": "B1-gRSUVYYX",
"pinKey": "SkSuD6LMb"
},
"output": {
"nodeId": "Hk6RBINtYX",
"pinKey": "H1A0CH3PYm"
}
},
{
"id": "SyC65NFKQ",
"input": {
"nodeId": "SyETcEtKm",
"pinKey": "SkSuD6LMb"
},
"output": {
"nodeId": "Hk6RBINtYX",
"pinKey": "BJpCRr2vt7"
}
},
{
"id": "r1u9Ys19X",
"input": {
"nodeId": "ByXASI4FKm",
"pinKey": "__in__"
},
"output": {
"nodeId": "Byj0rUNKKQ",
"pinKey": "ByHmL0uHPk-"
}
},
{
"id": "rJQn9okcQ",
"input": {
"nodeId": "Hk6RBINtYX",
"pinKey": "rygl0RH3wtm"
},
"output": {
"nodeId": "Byj0rUNKKQ",
"pinKey": "ByHmL0uHPk-"
}
},
{
"id": "rkEsw7cYQ",
"input": {
"nodeId": "SyFdPQqtQ",
"pinKey": "ByU7LRuSPkW"
},
"output": {
"nodeId": "B1-gRSUVYYX",
"pinKey": "Bk4gU0drwJ-"
}
},
{
"id": "rkzbRBIVKY7",
"input": {
"nodeId": "HydRr8NttQ",
"pinKey": "r1JWmAxzQ"
},
"output": {
"nodeId": "Sy2CBUNYt7",
"pinKey": "__out__"
}
}
],
"nodes": [
{
"boundLiterals": {
"Skre8ROSv1-": "5"
},
"id": "B1-gRSUVYYX",
"position": {
"x": 612,
"y": 612
},
"type": "xod/core/delay"
},
{
"id": "B19RHUNYt7",
"label": "RST",
"position": {
"x": 374,
"y": 510
},
"type": "xod/patch-nodes/from-bus"
},
{
"boundLiterals": {
"rkZ8oIj0-m": "\"\"lum\":\""
},
"id": "BJCSI4tYQ",
"position": {
"x": 272,
"y": 612
},
"type": "xod/stream/pass-from-sequence"
},
{
"id": "ByXASI4FKm",
"label": "RST",
"position": {
"x": 408,
"y": 306
},
"type": "xod/patch-nodes/to-bus"
},
{
"id": "Byj0rUNKKQ",
"position": {
"x": 408,
"y": 204
},
"type": "xod/core/any"
},
{
"id": "H1BCFNKKm",
"label": "AGAIN",
"position": {
"x": 578,
"y": 816
},
"type": "xod/patch-nodes/to-bus"
},
{
"boundLiterals": {
"HJjCAB2DF7": "\"dweet.io\"",
"ryYRCBhvFX": "\"/get/latest/dweet/for/xod-esp8266-iot\""
},
"id": "Hk6RBINtYX",
"position": {
"x": 271,
"y": 407
},
"type": "@/http-request(esp8266-mcu-inet)"
},
{
"id": "HydRr8NttQ",
"position": {
"x": 272,
"y": 816
},
"type": "xod/stream/parse-integer"
},
{
"id": "Sy2CBUNYt7",
"label": "RST",
"position": {
"x": 340,
"y": 714
},
"type": "xod/patch-nodes/from-bus"
},
{
"boundLiterals": {
"Skre8ROSv1-": "2"
},
"id": "SyETcEtKm",
"position": {
"x": 476,
"y": 612
},
"type": "xod/core/delay"
},
{
"id": "SyFdPQqtQ",
"position": {
"x": 510,
"y": 714
},
"type": "xod/core/any"
},
{
"boundLiterals": {
"B1rSeJlnZ": "100",
"HkFBgJehW": "1"
},
"id": "r1F8u4ttm",
"position": {
"x": 136,
"y": 918
},
"type": "xod/math/map-clip"
},
{
"id": "rkMCr8EtYX",
"label": "AGAIN",
"position": {
"x": 442,
"y": 102
},
"type": "xod/patch-nodes/from-bus"
},
{
"boundLiterals": {
"B1oqkTnIb": "A2"
},
"id": "rkWAH8EYtQ",
"position": {
"x": 238,
"y": 1020
},
"type": "xod/common-hardware/led"
},
{
"id": "rkv29jyc7",
"position": {
"x": 578,
"y": 714
},
"type": "xod/core/defer"
},
{
"boundLiterals": {
"H1z0HpF8Km": "\"password\"",
"HJZCrpKLYX": "\"ssid\""
},
"id": "ryJlRBU4FYQ",
"position": {
"x": 272,
"y": 102
},
"type": "@/connect"
}
]
}

View File

@@ -0,0 +1,205 @@
{
"comments": [
{
"content": "⚠️ Make sure to specify SSID and password of your WiFi network",
"id": "BklorYcYX",
"position": {
"x": 306,
"y": 102
},
"size": {
"height": 51,
"width": 272
}
},
{
"content": "Just print result to serial byte by byte",
"id": "HJDFvP9KX",
"position": {
"x": 238,
"y": 510
},
"size": {
"height": 51,
"width": 170
}
}
],
"links": [
{
"id": "Bk8t7TwKX",
"input": {
"nodeId": "SkMy6faPFQ",
"pinKey": "rklUo8jA-Q"
},
"output": {
"nodeId": "Hy7K7awF7",
"pinKey": "r1E0RH3vYQ"
}
},
{
"id": "HJByazTvY7",
"input": {
"nodeId": "SJlyTMpPYX",
"pinKey": "BJYbP7CZm"
},
"output": {
"nodeId": "SkMy6faPFQ",
"pinKey": "SkSGwoAZQ"
}
},
{
"id": "HJXeNTwKm",
"input": {
"nodeId": "Hy7K7awF7",
"pinKey": "rygl0RH3wtm"
},
"output": {
"nodeId": "r1ArzjUFm",
"pinKey": "HyLAraK8Km"
}
},
{
"id": "S1HtmpPt7",
"input": {
"nodeId": "SkMy6faPFQ",
"pinKey": "B18iIoA-m"
},
"output": {
"nodeId": "Hy7K7awF7",
"pinKey": "Hku0ArhDYX"
}
},
{
"id": "SkEVhP5YX",
"input": {
"nodeId": "BkefrP9K7",
"pinKey": "BkHrP2I-m"
},
"output": {
"nodeId": "Hyg42D5KQ",
"pinKey": "Sk450OL-X"
}
},
{
"id": "SkGGrPqFm",
"input": {
"nodeId": "BkefrP9K7",
"pinKey": "rJaSP2UZm"
},
"output": {
"nodeId": "SJlyTMpPYX",
"pinKey": "By5Vv7C-7"
}
},
{
"id": "r1Kk6GpDYX",
"input": {
"nodeId": "SJlyTMpPYX",
"pinKey": "r1CWwm0b7"
},
"output": {
"nodeId": "SkMy6faPFQ",
"pinKey": "SkYZwiRbm"
}
},
{
"id": "r1wV3D9FX",
"input": {
"nodeId": "r1ArzjUFm",
"pinKey": "ryRHTFItQ"
},
"output": {
"nodeId": "Hyg42D5KQ",
"pinKey": "Sk0ktvLO7"
}
},
{
"id": "rkQzBP5t7",
"input": {
"nodeId": "BkefrP9K7",
"pinKey": "Hyz0PhIbm"
},
"output": {
"nodeId": "SJlyTMpPYX",
"pinKey": "r1XBwQCWQ"
}
},
{
"id": "ryfo7pwFm",
"input": {
"nodeId": "Hy7K7awF7",
"pinKey": "S1Tl8hwFQ"
},
"output": {
"nodeId": "r1ArzjUFm",
"pinKey": "H1Gd15UFQ"
}
}
],
"nodes": [
{
"id": "BkefrP9K7",
"position": {
"x": 136,
"y": 510
},
"type": "xod/uart/write-byte"
},
{
"boundLiterals": {
"HJjCAB2DF7": "\"api.xod.io\"",
"ryYRCBhvFX": "\"/httpbin/ip\""
},
"id": "Hy7K7awF7",
"position": {
"x": 170,
"y": 204
},
"type": "@/http-request(esp8266-mcu-inet)"
},
{
"id": "Hyg42D5KQ",
"position": {
"x": 136,
"y": 0
},
"type": "xod/uart/uart-0"
},
{
"boundLiterals": {
"S1a8PX0Wm": "On Boot",
"S1bGvmAWQ": "'\"'"
},
"id": "SJlyTMpPYX",
"position": {
"x": 170,
"y": 408
},
"type": "xod/stream/pass-until"
},
{
"boundLiterals": {
"rkZ8oIj0-m": "\"origin\": \"\""
},
"id": "SkMy6faPFQ",
"position": {
"x": 170,
"y": 306
},
"type": "xod/stream/pass-from-sequence"
},
{
"boundLiterals": {
"H1z0HpF8Km": "\"password\"",
"HJZCrpKLYX": "\"ssid\""
},
"id": "r1ArzjUFm",
"position": {
"x": 170,
"y": 102
},
"type": "@/connect"
}
]
}

View File

@@ -0,0 +1,569 @@
{
"description": "Performs an HTTP request and returns the response as a stream of characters",
"links": [
{
"id": "B1G_QOhwtX",
"input": {
"nodeId": "ryE1I3vFm",
"pinKey": "ByZE6AjDt7"
},
"output": {
"nodeId": "B1bOmdhwF7",
"pinKey": "__out__"
}
},
{
"id": "B1MJahPFm",
"input": {
"nodeId": "Hku0ArhDYX",
"pinKey": "__in__"
},
"output": {
"nodeId": "SJSC3hDKQ",
"pinKey": "HyNOn3vt7"
}
},
{
"id": "BkLW0AS3wK7",
"input": {
"nodeId": "H1ACr2vFX",
"pinKey": "SkQFtMKZm"
},
"output": {
"nodeId": "ByWlRArnDFQ",
"pinKey": "__out__"
}
},
{
"id": "Bk_eCCrnDKm",
"input": {
"nodeId": "B1U0CH2PFQ",
"pinKey": "BkeKcj6ZZ-$1"
},
"output": {
"nodeId": "Hyg00BnPK7",
"pinKey": "r1H_oipZb"
}
},
{
"id": "Bkh0n3vtm",
"input": {
"nodeId": "SJSC3hDKQ",
"pinKey": "B1WEdh3Ptm"
},
"output": {
"nodeId": "BJO382PtQ",
"pinKey": "HyQ6rIhDtX"
}
},
{
"id": "ByzgSDnPKQ",
"input": {
"nodeId": "B1U0CH2PFQ",
"pinKey": "Hkqu9oaWb"
},
"output": {
"nodeId": "BkZeBwhvYm",
"pinKey": "__out__"
}
},
{
"id": "H13gv3Dt7",
"input": {
"nodeId": "BJO382PtQ",
"pinKey": "SJf6BU2PKQ"
},
"output": {
"nodeId": "ryE1I3vFm",
"pinKey": "r1EpRjDYQ"
}
},
{
"id": "H1ExHP2wtX",
"input": {
"nodeId": "ryE1I3vFm",
"pinKey": "ryQ46CovFm"
},
"output": {
"nodeId": "BkXgHvhwtX",
"pinKey": "__out__"
}
},
{
"id": "H1cC22vYX",
"input": {
"nodeId": "SJSC3hDKQ",
"pinKey": "SyKY2nPtQ"
},
"output": {
"nodeId": "ryE1I3vFm",
"pinKey": "H1mYNnvY7"
}
},
{
"id": "H1egBvhDY7",
"input": {
"nodeId": "H1lBv2wF7",
"pinKey": "__in__"
},
"output": {
"nodeId": "HJjCAB2DF7",
"pinKey": "__out__"
}
},
{
"id": "HJCgARrnPKm",
"input": {
"nodeId": "H1ACr2vFX",
"pinKey": "Hyd95MK-m"
},
"output": {
"nodeId": "BJcR0ShvYQ",
"pinKey": "__out__"
}
},
{
"id": "HJXk6nvF7",
"input": {
"nodeId": "r1E0RH3vYQ",
"pinKey": "__in__"
},
"output": {
"nodeId": "SJSC3hDKQ",
"pinKey": "BktNOnnDYQ"
}
},
{
"id": "HklnrDhvt7",
"input": {
"nodeId": "rknSDnPYQ",
"pinKey": "__in__"
},
"output": {
"nodeId": "SyM00ShDY7",
"pinKey": "__out__"
}
},
{
"id": "HkwZRRB3wYX",
"input": {
"nodeId": "H1ACr2vFX",
"pinKey": "Sy5v9zFZ7"
},
"output": {
"nodeId": "Hkv0CrnPYQ",
"pinKey": "__out__"
}
},
{
"id": "HyNnrDhwt7",
"input": {
"nodeId": "ryE1I3vFm",
"pinKey": "ryL4pAjPKX"
},
"output": {
"nodeId": "r1QnBD2vFm",
"pinKey": "__out__"
}
},
{
"id": "S1l_mO2DYX",
"input": {
"nodeId": "B1_QuhPtQ",
"pinKey": "__in__"
},
"output": {
"nodeId": "rygl0RH3wtm",
"pinKey": "__out__"
}
},
{
"id": "SJ0nI2DKX",
"input": {
"nodeId": "BJO382PtQ",
"pinKey": "rJX8L2vKQ"
},
"output": {
"nodeId": "ryE1I3vFm",
"pinKey": "H1mYNnvY7"
}
},
{
"id": "SJ7682vFm",
"input": {
"nodeId": "BJO382PtQ",
"pinKey": "BkW6rLnwFQ"
},
"output": {
"nodeId": "H1ACr2vFX",
"pinKey": "H1leYGFbm"
}
},
{
"id": "SJdCUhwFX",
"input": {
"nodeId": "rJ7C0HhPKX",
"pinKey": "ryv7IRdSP1b"
},
"output": {
"nodeId": "BJO382PtQ",
"pinKey": "Bk6SU2wtQ"
}
},
{
"id": "SJzhrwnvtQ",
"input": {
"nodeId": "Hyg00BnPK7",
"pinKey": "BJlHojaWZ"
},
"output": {
"nodeId": "HyW3SD3vF7",
"pinKey": "__out__"
}
},
{
"id": "SkTgA0B3vYQ",
"input": {
"nodeId": "H1ACr2vFX",
"pinKey": "BJqntfKbm"
},
"output": {
"nodeId": "B1U0CH2PFQ",
"pinKey": "rksccsp-W"
}
},
{
"id": "SkgbvhDF7",
"input": {
"nodeId": "rJ7C0HhPKX",
"pinKey": "ByU7LRuSPkW"
},
"output": {
"nodeId": "ryE1I3vFm",
"pinKey": "B1ENaAjwtm"
}
},
{
"id": "r1EWInDFQ",
"input": {
"nodeId": "ryE1I3vFm",
"pinKey": "SkEJyhvFQ"
},
"output": {
"nodeId": "S1Tl8hwFQ",
"pinKey": "__out__"
}
},
{
"id": "ry5l0RS2vYX",
"input": {
"nodeId": "H1ACr2vFX",
"pinKey": "HkcCKGYZ7"
},
"output": {
"nodeId": "ryYRCBhvFX",
"pinKey": "__out__"
}
},
{
"id": "ry8yT2wt7",
"input": {
"nodeId": "BJpCRr2vt7",
"pinKey": "__in__"
},
"output": {
"nodeId": "SJSC3hDKQ",
"pinKey": "rkANu2hwtQ"
}
},
{
"id": "rytg0RBnDtX",
"input": {
"nodeId": "H1A0CH3PYm",
"pinKey": "__in__"
},
"output": {
"nodeId": "rJ7C0HhPKX",
"pinKey": "ByHmL0uHPk-"
}
}
],
"nodes": [
{
"arityLevel": 2,
"boundLiterals": {
"BkeKcj6ZZ": "\":\""
},
"id": "B1U0CH2PFQ",
"position": {
"x": 238,
"y": 306
},
"type": "xod/core/concat"
},
{
"id": "B1_QuhPtQ",
"label": "INIT",
"position": {
"x": 475,
"y": 101
},
"type": "xod/patch-nodes/to-bus"
},
{
"id": "B1bOmdhwF7",
"label": "INIT",
"position": {
"x": 102,
"y": 204
},
"type": "xod/patch-nodes/from-bus"
},
{
"id": "BJO382PtQ",
"position": {
"x": 34,
"y": 510
},
"type": "@/send"
},
{
"boundLiterals": {
"__out__": "\"\""
},
"description": "Additional headers",
"id": "BJcR0ShvYQ",
"label": "HDRS",
"position": {
"x": 339,
"y": -1
},
"type": "xod/patch-nodes/input-string"
},
{
"description": "Pulses when all response data is received and the connection is closed",
"id": "BJpCRr2vt7",
"label": "DONE",
"position": {
"x": 135,
"y": 713
},
"type": "xod/patch-nodes/output-pulse"
},
{
"id": "BkXgHvhwtX",
"label": "HOST",
"position": {
"x": 34,
"y": 204
},
"type": "xod/patch-nodes/from-bus"
},
{
"id": "BkZeBwhvYm",
"label": "HOST",
"position": {
"x": 238,
"y": 204
},
"type": "xod/patch-nodes/from-bus"
},
{
"boundLiterals": {
"__out__": "\"GET\""
},
"description": "An HTTP method (e.g., GET, POST, PUT, or DELETE)",
"id": "ByWlRArnDFQ",
"label": "METH",
"position": {
"x": 203,
"y": -1
},
"type": "xod/patch-nodes/input-string"
},
{
"description": "Pulses if the request failed",
"id": "H1A0CH3PYm",
"label": "ERR",
"position": {
"x": 203,
"y": 713
},
"type": "xod/patch-nodes/output-pulse"
},
{
"boundLiterals": {
"HkcCKGYZ7": "\"/\""
},
"id": "H1ACr2vFX",
"position": {
"x": 204,
"y": 408
},
"type": "xod/net/format-http-request"
},
{
"id": "H1lBv2wF7",
"label": "HOST",
"position": {
"x": 67,
"y": 101
},
"type": "xod/patch-nodes/to-bus"
},
{
"boundLiterals": {
"__out__": "\"\""
},
"description": "The domain name of the server",
"id": "HJjCAB2DF7",
"label": "HOST",
"position": {
"x": 67,
"y": -1
},
"type": "xod/patch-nodes/input-string"
},
{
"description": "The last received character from the response",
"id": "Hku0ArhDYX",
"label": "CHAR",
"position": {
"x": -1,
"y": 713
},
"type": "xod/patch-nodes/output-byte"
},
{
"boundLiterals": {
"__out__": "\"\""
},
"description": "The request body (optional)",
"id": "Hkv0CrnPYQ",
"label": "BODY",
"position": {
"x": 407,
"y": -1
},
"type": "xod/patch-nodes/input-string"
},
{
"id": "HyW3SD3vF7",
"label": "PORT",
"position": {
"x": 306,
"y": 102
},
"type": "xod/patch-nodes/from-bus"
},
{
"boundLiterals": {
"HJTIija-W": "0"
},
"id": "Hyg00BnPK7",
"position": {
"x": 306,
"y": 204
},
"type": "xod/core/format-number"
},
{
"description": "An internet connection",
"id": "S1Tl8hwFQ",
"label": "INET",
"position": {
"x": 0,
"y": 0
},
"type": "@/input-esp8266-mcu-inet"
},
{
"id": "SJSC3hDKQ",
"position": {
"x": 0,
"y": 612
},
"type": "@/receive"
},
{
"boundLiterals": {
"__out__": "80"
},
"description": "A port number on which the server is listening. In most configurations, HTTP web servers listen at port 80.",
"id": "SyM00ShDY7",
"label": "PORT",
"position": {
"x": 135,
"y": -1
},
"type": "xod/patch-nodes/input-number"
},
{
"description": "Pulses when a new response character is received",
"id": "r1E0RH3vYQ",
"label": "RCV",
"position": {
"x": 67,
"y": 713
},
"type": "xod/patch-nodes/output-pulse"
},
{
"id": "r1QnBD2vFm",
"label": "PORT",
"position": {
"x": 68,
"y": 204
},
"type": "xod/patch-nodes/from-bus"
},
{
"id": "rJ7C0HhPKX",
"position": {
"x": 203,
"y": 611
},
"type": "xod/core/any"
},
{
"id": "rknSDnPYQ",
"label": "PORT",
"position": {
"x": 135,
"y": 101
},
"type": "xod/patch-nodes/to-bus"
},
{
"id": "ryE1I3vFm",
"position": {
"x": 0,
"y": 306
},
"type": "@/open-tcp"
},
{
"boundLiterals": {
"__out__": "\"/\""
},
"description": "A path to the requested resource",
"id": "ryYRCBhvFX",
"label": "PATH",
"position": {
"x": 271,
"y": -1
},
"type": "xod/patch-nodes/input-string"
},
{
"description": "Begin the request",
"id": "rygl0RH3wtm",
"label": "INIT",
"position": {
"x": 475,
"y": -1
},
"type": "xod/patch-nodes/input-pulse"
}
]
}

View File

@@ -0,0 +1,20 @@
struct State {
};
// clang-format off
{{ GENERATED_CODE }}
// clang-format on
void evaluate(Context ctx) {
if (!isInputDirty<input_CHK>(ctx))
return;
auto client = getValue<input_SOCK>(ctx);
if (client->connected()) {
emitValue<output_Y>(ctx, 1);
} else {
emitValue<output_N>(ctx, 1);
}
}

View File

@@ -0,0 +1,53 @@
{
"description": "Checks if a TCP connection is open",
"nodes": [
{
"id": "BkXkhxTDt7",
"position": {
"x": -1,
"y": 101
},
"type": "xod/patch-nodes/not-implemented-in-xod"
},
{
"description": "A socket",
"id": "HkEhxaDYX",
"label": "SOCK",
"position": {
"x": 0,
"y": 0
},
"type": "@/input-socket"
},
{
"description": "Pulses if the connection is open",
"id": "Hkkhe6vYX",
"label": "Y",
"position": {
"x": -1,
"y": 203
},
"type": "xod/patch-nodes/output-pulse"
},
{
"description": "Perform the check",
"id": "r1f1heaDtQ",
"label": "CHK",
"position": {
"x": 101,
"y": -1
},
"type": "xod/patch-nodes/input-pulse"
},
{
"description": "Pulses if the connection is closed",
"id": "rJgkhxTvKX",
"label": "N",
"position": {
"x": 101,
"y": 203
},
"type": "xod/patch-nodes/output-pulse"
}
]
}

View File

@@ -0,0 +1,12 @@
struct State {
};
// clang-format off
{{ GENERATED_CODE }}
// clang-format on
void evaluate(Context ctx) {
auto inet = getValue<input_INET>(ctx);
emitValue<output_IP>(ctx, (ValueType<output_IP>::T)inet->localIP());
}

View File

@@ -0,0 +1,33 @@
{
"description": "Gets a local IP address",
"nodes": [
{
"id": "BJW3uVtwYm",
"position": {
"x": -1,
"y": 101
},
"type": "xod/patch-nodes/not-implemented-in-xod"
},
{
"description": "An internet connection",
"id": "SkGtVFvY7",
"label": "INET",
"position": {
"x": 0,
"y": 0
},
"type": "@/input-esp8266-mcu-inet"
},
{
"description": "The IP address",
"id": "ryxn_NYPKX",
"label": "IP",
"position": {
"x": -1,
"y": 203
},
"type": "xod/net/output-ip-address"
}
]
}

View File

@@ -0,0 +1,36 @@
// clang-format off
{{#global}}
#include <ESP8266WiFi.h>
{{/global}}
// clang-format on
struct State {
WiFiClient client;
};
// clang-format off
{{ GENERATED_CODE }}
// clang-format on
void evaluate(Context ctx) {
if (!isInputDirty<input_CONN>(ctx))
return;
auto serverName = getValue<input_SRV>(ctx);
auto len = length(serverName);
char serverNameBuff[len + 1];
dump(serverName, serverNameBuff);
serverNameBuff[len] = '\0';
auto port = getValue<input_PORT>(ctx);
auto state = getState(ctx);
if (state->client.connect(serverNameBuff, port)) {
emitValue<output_DONE>(ctx, 1);
} else {
emitValue<output_ERR>(ctx, 1);
}
emitValue<output_SOCK>(ctx, &state->client);
}

View File

@@ -0,0 +1,89 @@
{
"description": "Open a TCP connection to the specified server",
"nodes": [
{
"description": "Pulses when opening failed",
"id": "B1ENaAjwtm",
"label": "ERR",
"position": {
"x": 203,
"y": 203
},
"type": "xod/patch-nodes/output-pulse"
},
{
"description": "Open the connection",
"id": "ByZE6AjDt7",
"label": "CONN",
"position": {
"x": 305,
"y": -1
},
"type": "xod/patch-nodes/input-pulse"
},
{
"id": "H1BNpCiPK7",
"position": {
"x": -1,
"y": 101
},
"type": "xod/patch-nodes/not-implemented-in-xod"
},
{
"description": "A socket",
"id": "H1mYNnvY7",
"label": "SOCK",
"position": {
"x": 0,
"y": 204
},
"type": "@/output-socket"
},
{
"description": "An internet connection",
"id": "SkEJyhvFQ",
"label": "INET",
"position": {
"x": 0,
"y": 0
},
"type": "@/input-esp8266-mcu-inet"
},
{
"description": "Pulses when the connection is successfully open",
"id": "r1EpRjDYQ",
"label": "DONE",
"position": {
"x": 101,
"y": 203
},
"type": "xod/patch-nodes/output-pulse"
},
{
"boundLiterals": {
"__out__": "80"
},
"description": "A destination server port number",
"id": "ryL4pAjPKX",
"label": "PORT",
"position": {
"x": 203,
"y": -1
},
"type": "xod/patch-nodes/input-number"
},
{
"boundLiterals": {
"__out__": "\"www.google.com\""
},
"description": "Server name",
"id": "ryQ46CovFm",
"label": "SRV",
"position": {
"x": 101,
"y": -1
},
"type": "xod/patch-nodes/input-string"
}
]
}

View File

@@ -0,0 +1,9 @@
{
"authors": [
"XOD"
],
"description": "Support for ESP8266-based MCUs.",
"license": "AGPL-3.0",
"name": "esp8266-mcu",
"version": "0.25.0"
}

View File

@@ -0,0 +1,22 @@
struct State {
};
// clang-format off
{{ GENERATED_CODE }}
// clang-format on
void evaluate(Context ctx) {
if (!isInputDirty<input_READ>(ctx))
return;
auto client = getValue<input_SOCK>(ctx);
int b = client->read();
if (b < 0) {
emitValue<output_ERR>(ctx, 1);
return;
}
emitValue<output_B>(ctx, (uint8_t)b);
emitValue<output_DONE>(ctx, 1);
}

View File

@@ -0,0 +1,63 @@
{
"description": "Read a single byte of the response from an opened connection",
"nodes": [
{
"description": "Pulses when the byte is read",
"id": "BJX3fx6vtm",
"label": "DONE",
"position": {
"x": 67,
"y": 203
},
"type": "xod/patch-nodes/output-pulse"
},
{
"description": "The last read byte",
"id": "Hyz3GeTPY7",
"label": "B",
"position": {
"x": -1,
"y": 203
},
"type": "xod/patch-nodes/output-byte"
},
{
"id": "S1-3MlpwKm",
"position": {
"x": -1,
"y": 101
},
"type": "xod/patch-nodes/not-implemented-in-xod"
},
{
"description": "Pulses when there is no byte to read",
"id": "rJQtld157",
"label": "ERR",
"position": {
"x": 136,
"y": 204
},
"type": "xod/patch-nodes/output-pulse"
},
{
"description": "Read the byte",
"id": "rJhfg6wYm",
"label": "READ",
"position": {
"x": 67,
"y": -1
},
"type": "xod/patch-nodes/input-pulse"
},
{
"description": "A socket",
"id": "ry4QlaDYQ",
"label": "SOCK",
"position": {
"x": 0,
"y": 0
},
"type": "@/input-socket"
}
]
}

View File

@@ -0,0 +1,333 @@
{
"description": "Read a response from an opened connection as a stream of bytes until it closes",
"links": [
{
"id": "B1xvVG3Jc7",
"input": {
"nodeId": "HkwNGhk5m",
"pinKey": "__in__"
},
"output": {
"nodeId": "SkP8WpPKX",
"pinKey": "HJhXDIY9-"
}
},
{
"id": "BkgmeWavtm",
"input": {
"nodeId": "By60xaPYQ",
"pinKey": "ry4QlaDYQ"
},
"output": {
"nodeId": "Syme-6wFm",
"pinKey": "__out__"
}
},
{
"id": "ByYW4Yy5m",
"input": {
"nodeId": "By60xaPYQ",
"pinKey": "rJhfg6wYm"
},
"output": {
"nodeId": "B1b8WpvKm",
"pinKey": "ByHmL0uHPk-"
}
},
{
"id": "H18vWTwKm",
"input": {
"nodeId": "SkP8WpPKX",
"pinKey": "BJI7P8t9Z"
},
"output": {
"nodeId": "Hy0U-TPKQ",
"pinKey": "ByHmL0uHPk-"
}
},
{
"id": "HkMPbaPFm",
"input": {
"nodeId": "Hy0U-TPKQ",
"pinKey": "ryv7IRdSP1b"
},
"output": {
"nodeId": "By60xaPYQ",
"pinKey": "BJX3fx6vtm"
}
},
{
"id": "Hy__bpwY7",
"input": {
"nodeId": "BktNOnnDYQ",
"pinKey": "__in__"
},
"output": {
"nodeId": "By60xaPYQ",
"pinKey": "BJX3fx6vtm"
}
},
{
"id": "S1RrWpvFm",
"input": {
"nodeId": "SkKr-6PYm",
"pinKey": "r1eDMb6vKm"
},
"output": {
"nodeId": "SJT1-TwtQ",
"pinKey": "rJgkhxTvKX"
}
},
{
"id": "S1gdq2nwKm",
"input": {
"nodeId": "Hyd9hnvYm",
"pinKey": "__in__"
},
"output": {
"nodeId": "SyKY2nPtQ",
"pinKey": "__out__"
}
},
{
"id": "S1oP-TPF7",
"input": {
"nodeId": "B1b8WpvKm",
"pinKey": "ryv7IRdSP1b"
},
"output": {
"nodeId": "B1WEdh3Ptm",
"pinKey": "__out__"
}
},
{
"id": "SkNv-TDtQ",
"input": {
"nodeId": "Hy0U-TPKQ",
"pinKey": "ByU7LRuSPkW"
},
"output": {
"nodeId": "SJT1-TwtQ",
"pinKey": "Hkkhe6vYX"
}
},
{
"id": "Sy5u-TPK7",
"input": {
"nodeId": "HyNOn3vt7",
"pinKey": "__in__"
},
"output": {
"nodeId": "By60xaPYQ",
"pinKey": "Hyz3GeTPY7"
}
},
{
"id": "Symd-Tvt7",
"input": {
"nodeId": "rkANu2hwtQ",
"pinKey": "__in__"
},
"output": {
"nodeId": "SkKr-6PYm",
"pinKey": "ByPfZaPKQ"
}
},
{
"id": "r1xLxWaPF7",
"input": {
"nodeId": "SJT1-TwtQ",
"pinKey": "HkEhxaDYX"
},
"output": {
"nodeId": "BkUg-awK7",
"pinKey": "__out__"
}
},
{
"id": "rJx0Vfh19X",
"input": {
"nodeId": "B1b8WpvKm",
"pinKey": "ByU7LRuSPkW"
},
"output": {
"nodeId": "r1CVz3ycQ",
"pinKey": "__out__"
}
},
{
"id": "rkewIOt19X",
"input": {
"nodeId": "SkKr-6PYm",
"pinKey": "SJiGWTPKm"
},
"output": {
"nodeId": "HyDIuKJ9m",
"pinKey": "__out__"
}
},
{
"id": "rkib4Ykcm",
"input": {
"nodeId": "SJT1-TwtQ",
"pinKey": "r1f1heaDtQ"
},
"output": {
"nodeId": "By60xaPYQ",
"pinKey": "rJQtld157"
}
}
],
"nodes": [
{
"description": "Begin reading",
"id": "B1WEdh3Ptm",
"label": "BGN",
"position": {
"x": 68,
"y": 0
},
"type": "xod/patch-nodes/input-pulse"
},
{
"id": "B1b8WpvKm",
"position": {
"x": 68,
"y": 102
},
"type": "xod/core/any"
},
{
"id": "BkUg-awK7",
"label": "SOCK",
"position": {
"x": 170,
"y": 306
},
"type": "xod/patch-nodes/from-bus"
},
{
"description": "Pulses when a new byte is read",
"id": "BktNOnnDYQ",
"position": {
"x": 67,
"y": 611
},
"type": "xod/patch-nodes/output-pulse"
},
{
"id": "By60xaPYQ",
"position": {
"x": 34,
"y": 204
},
"type": "@/read-byte"
},
{
"id": "HkwNGhk5m",
"label": "AGAIN",
"position": {
"x": 204,
"y": 510
},
"type": "xod/patch-nodes/to-bus"
},
{
"id": "Hy0U-TPKQ",
"position": {
"x": 136,
"y": 408
},
"type": "xod/core/any"
},
{
"id": "HyDIuKJ9m",
"label": "SOCK",
"position": {
"x": 272,
"y": 510
},
"type": "xod/patch-nodes/from-bus"
},
{
"description": "The last read byte",
"id": "HyNOn3vt7",
"position": {
"x": 33,
"y": 611
},
"type": "xod/patch-nodes/output-byte"
},
{
"id": "Hyd9hnvYm",
"label": "SOCK",
"position": {
"x": 0,
"y": 102
},
"type": "xod/patch-nodes/to-bus"
},
{
"id": "SJT1-TwtQ",
"position": {
"x": 204,
"y": 306
},
"type": "@/is-open"
},
{
"id": "SkKr-6PYm",
"position": {
"x": 306,
"y": 510
},
"type": "@/close"
},
{
"id": "SkP8WpPKX",
"position": {
"x": 204,
"y": 408
},
"type": "xod/core/defer"
},
{
"description": "A socket",
"id": "SyKY2nPtQ",
"label": "SOCK",
"position": {
"x": 0,
"y": 0
},
"type": "@/input-socket"
},
{
"id": "Syme-6wFm",
"label": "SOCK",
"position": {
"x": 0,
"y": 204
},
"type": "xod/patch-nodes/from-bus"
},
{
"id": "r1CVz3ycQ",
"label": "AGAIN",
"position": {
"x": 102,
"y": 0
},
"type": "xod/patch-nodes/from-bus"
},
{
"description": "Pulses when the connection is closed",
"id": "rkANu2hwtQ",
"label": "CLS",
"position": {
"x": 306,
"y": 612
},
"type": "xod/patch-nodes/output-pulse"
}
]
}

View File

@@ -0,0 +1,29 @@
struct State {
};
// clang-format off
{{ GENERATED_CODE }}
// clang-format on
void evaluate(Context ctx) {
if (!isInputDirty<input_SND>(ctx))
return;
auto client = getValue<input_SOCK>(ctx);
auto msg = getValue<input_MSG>(ctx);
size_t lastWriteSize;
for (auto it = msg.iterate(); it; ++it) {
lastWriteSize = client->write((char)*it);
if (lastWriteSize == 0) {
emitValue<output_ERR>(ctx, 1);
return;
}
}
client->flush();
emitValue<output_DONE>(ctx, 1);
}

View File

@@ -0,0 +1,63 @@
{
"description": "Send a message through an opened TCP connection",
"nodes": [
{
"description": "Pulses when sending failed (for example, the connection is not open)",
"id": "Bk6SU2wtQ",
"label": "ERR",
"position": {
"x": 67,
"y": 203
},
"type": "xod/patch-nodes/output-pulse"
},
{
"description": "The message to send",
"id": "BkW6rLnwFQ",
"label": "MSG",
"position": {
"x": 101,
"y": -1
},
"type": "xod/patch-nodes/input-string"
},
{
"description": "Pulses when the message is successfully sent",
"id": "HyQ6rIhDtX",
"label": "DONE",
"position": {
"x": -1,
"y": 203
},
"type": "xod/patch-nodes/output-pulse"
},
{
"description": "Send the message",
"id": "SJf6BU2PKQ",
"label": "SND",
"position": {
"x": 203,
"y": -1
},
"type": "xod/patch-nodes/input-pulse"
},
{
"description": "A socket",
"id": "rJX8L2vKQ",
"label": "SOCK",
"position": {
"x": 0,
"y": 0
},
"type": "@/input-socket"
},
{
"id": "rJeprU3vYX",
"position": {
"x": -1,
"y": 101
},
"type": "xod/patch-nodes/not-implemented-in-xod"
}
]
}

View File

@@ -0,0 +1,31 @@
// clang-format off
{{#global}}
#include <ESP8266WiFi.h>
{{/global}}
// clang-format on
using Type = WiFiClient*;
struct State {
Type client;
};
// clang-format off
{{ GENERATED_CODE }}
// clang-format on
void evaluate(Context ctx) {
auto state = getState(ctx);
if (isSettingUp()) {
// Normally, WiFiClient would be constructed on a
// pre-allocated buffer using a placement new operator.
// (xod-dev/esp8266/esp8266-device is a nice example)
// But this `evaluate` will be called only if someone
// forgot to link a "proper" `socket`(created with `open-tcp`).
state->client = new WiFiClient();
}
emitValue<output_OUT>(ctx, state->client);
}

View File

@@ -0,0 +1,28 @@
{
"nodes": [
{
"id": "B11KMhDtX",
"position": {
"x": 34,
"y": 204
},
"type": "xod/patch-nodes/output-self"
},
{
"id": "ByvuM2PF7",
"position": {
"x": 34,
"y": 102
},
"type": "xod/patch-nodes/not-implemented-in-xod"
},
{
"id": "H19dG2PKm",
"position": {
"x": 102,
"y": 102
},
"type": "xod/patch-nodes/utility"
}
]
}