From 5dd83fa6eeb15280ad2902e517690d7f76c52f80 Mon Sep 17 00:00:00 2001 From: Lorenzo Trivelli Date: Wed, 28 Jul 2021 09:31:35 +0200 Subject: [PATCH 01/13] Changed links in forms --- Thing.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Thing.h b/Thing.h index 25a6ea3..36a49b6 100644 --- a/Thing.h +++ b/Thing.h @@ -197,7 +197,7 @@ class ThingAction { // 2.11 Action object: A links array (An array of Link objects linking // to one or more representations of an Action resource, each with an // implied default rel=action.) - JsonArray inline_links = obj.createNestedArray("links"); + JsonArray inline_links = obj.createNestedArray("forms"); JsonObject inline_links_prop = inline_links.createNestedObject(); inline_links_prop["href"] = "/things/" + deviceId + "/actions/" + id; } @@ -297,7 +297,7 @@ class ThingItem { // 2.9 Property object: A links array (An array of Link objects linking // to one or more representations of a Property resource, each with an // implied default rel=property.) - JsonArray inline_links = obj.createNestedArray("links"); + JsonArray inline_links = obj.createNestedArray("forms"); JsonObject inline_links_prop = inline_links.createNestedObject(); inline_links_prop["href"] = "/things/" + deviceId + "/" + resourceType + "/" + id; @@ -724,7 +724,7 @@ class ThingDevice { type++; } - JsonArray links = descr.createNestedArray("links"); + JsonArray links = descr.createNestedArray("forms"); { JsonObject links_prop = links.createNestedObject(); links_prop["rel"] = "properties"; From 590f93ad30c4753bf13c926e73049c2ea7e8124a Mon Sep 17 00:00:00 2001 From: Lorenzo Trivelli Date: Thu, 5 Aug 2021 05:59:46 +0200 Subject: [PATCH 02/13] Removed all "global" forms from TD --- Thing.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Thing.h b/Thing.h index 36a49b6..d5bb3e8 100644 --- a/Thing.h +++ b/Thing.h @@ -461,7 +461,7 @@ class ThingEventObject { break; } - data["timestamp"] = timestamp; + //data["timestamp"] = timestamp; } }; @@ -695,10 +695,10 @@ class ThingDevice { #endif } - void serialize(JsonObject descr, String ip, uint16_t port) { + void serialize(JbsonObject descr, String ip, uint16_t port) { descr["id"] = this->id; descr["title"] = this->title; - descr["@context"] = "https://webthings.io/schemas"; + descr["@context"] = " https://www.w3.org/2019/wot/td/v1"; if (this->description != "") { descr["description"] = this->description; @@ -723,17 +723,15 @@ class ThingDevice { typeJson.add(*type); type++; } - + /* JsonArray links = descr.createNestedArray("forms"); { JsonObject links_prop = links.createNestedObject(); - links_prop["rel"] = "properties"; links_prop["href"] = "/things/" + this->id + "/properties"; } { JsonObject links_prop = links.createNestedObject(); - links_prop["rel"] = "actions"; links_prop["href"] = "/things/" + this->id + "/actions"; } @@ -742,11 +740,12 @@ class ThingDevice { links_prop["rel"] = "events"; links_prop["href"] = "/things/" + this->id + "/events"; } + */ #ifndef WITHOUT_WS { JsonObject links_prop = links.createNestedObject(); - links_prop["rel"] = "alternate"; + //links_prop["rel"] = "alternate"; if (port != 80) { char buffer[33]; From e2413bce7fe81dd288e3a7fe77a3c2eaf3bdceaa Mon Sep 17 00:00:00 2001 From: Lorenzo Trivelli Date: Thu, 5 Aug 2021 06:02:05 +0200 Subject: [PATCH 03/13] removed global forms from server --- WiFi101WebThingAdapter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WiFi101WebThingAdapter.h b/WiFi101WebThingAdapter.h index dc0fc5a..e07b528 100644 --- a/WiFi101WebThingAdapter.h +++ b/WiFi101WebThingAdapter.h @@ -308,7 +308,7 @@ class WebThingAdapter { handleError(); } return; - } else if (uri == deviceBase + "/properties") { + } /*else if (uri == deviceBase + "/properties") { if (method == HTTP_GET || method == HTTP_OPTIONS) { handleThingPropertiesGet(device->firstProperty); } else { @@ -330,7 +330,7 @@ class WebThingAdapter { } else { handleError(); } - return; + return;*/ } else { ThingProperty *property = device->firstProperty; while (property != nullptr) { From a2feda247cf7cdd581fdf53566128d441a6cf1ea Mon Sep 17 00:00:00 2001 From: Citrullin Date: Wed, 11 Aug 2021 13:20:28 +0200 Subject: [PATCH 04/13] Fix misspelling of JsonObject --- Thing.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Thing.h b/Thing.h index d5bb3e8..a9cd53e 100644 --- a/Thing.h +++ b/Thing.h @@ -695,7 +695,7 @@ class ThingDevice { #endif } - void serialize(JbsonObject descr, String ip, uint16_t port) { + void serialize(JsonObject descr, String ip, uint16_t port) { descr["id"] = this->id; descr["title"] = this->title; descr["@context"] = " https://www.w3.org/2019/wot/td/v1"; From 1adc91be3ef32e40b839c5aa099cc9373e813a04 Mon Sep 17 00:00:00 2001 From: Citrullin Date: Wed, 11 Aug 2021 13:27:10 +0200 Subject: [PATCH 05/13] Remove websocket --- ESPWebThingAdapter.h | 144 ---------------------------------------- Thing.h | 153 ------------------------------------------- 2 files changed, 297 deletions(-) diff --git a/ESPWebThingAdapter.h b/ESPWebThingAdapter.h index 6d96fcf..cbe76b4 100644 --- a/ESPWebThingAdapter.h +++ b/ESPWebThingAdapter.h @@ -158,15 +158,6 @@ class WebThingAdapter { void update() { #ifdef ESP8266 MDNS.update(); -#endif -#ifndef WITHOUT_WS - // * Send changed properties as defined in "4.5 propertyStatus message" - // Do this by looping over all devices and properties - ThingDevice *device = this->firstDevice; - while (device != nullptr) { - sendChangedProperties(device); - device = device->next; - } #endif } @@ -178,19 +169,6 @@ class WebThingAdapter { this->lastDevice->next = device; this->lastDevice = device; } - -#ifndef WITHOUT_WS - // Initiate the websocket instance - AsyncWebSocket *ws = new AsyncWebSocket("/things/" + device->id); - device->ws = ws; - // AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType - // type, void * arg, uint8_t *data, size_t len, ThingDevice* device - ws->onEvent(std::bind( - &WebThingAdapter::handleWS, this, std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5, std::placeholders::_6, device)); - this->server.addHandler(ws); -#endif } private: @@ -228,118 +206,6 @@ class WebThingAdapter { return false; } -#ifndef WITHOUT_WS - void sendErrorMsg(DynamicJsonDocument &prop, AsyncWebSocketClient &client, - int status, const char *msg) { - prop["error"] = msg; - prop["status"] = status; - String jsonStr; - serializeJson(prop, jsonStr); - client.text(jsonStr.c_str(), jsonStr.length()); - } - - void handleWS(AsyncWebSocket *server, AsyncWebSocketClient *client, - AwsEventType type, void *arg, const uint8_t *rawData, - size_t len, ThingDevice *device) { - if (type == WS_EVT_DISCONNECT || type == WS_EVT_ERROR) { - device->removeEventSubscriptions(client->id()); - return; - } - - // Ignore all others except data packets - if (type != WS_EVT_DATA) - return; - - // Only consider non fragmented data - AwsFrameInfo *info = (AwsFrameInfo *)arg; - if (!info->final || info->index != 0 || info->len != len) - return; - - // Web Thing only specifies text, not binary websocket transfers - if (info->opcode != WS_TEXT) - return; - - // In theory we could just have one websocket for all Things and react on - // the server->url() to route data. Controllers will however establish a - // separate websocket connection for each Thing anyway as of in the spec. - // For now each Thing stores its own Websocket connection object therefore. - - // Parse request - DynamicJsonDocument newProp(SMALL_JSON_DOCUMENT_SIZE); - auto error = deserializeJson(newProp, rawData, len); - if (error) { - sendErrorMsg(newProp, *client, 400, "Invalid json"); - return; - } - - String messageType = newProp["messageType"].as(); - JsonVariant dataVariant = newProp["data"]; - if (!dataVariant.is()) { - sendErrorMsg(newProp, *client, 400, "data must be an object"); - return; - } - - JsonObject data = dataVariant.as(); - - if (messageType == "setProperty") { - for (JsonPair kv : data) { - device->setProperty(kv.key().c_str(), kv.value()); - } - } else if (messageType == "requestAction") { - for (JsonPair kv : data) { - DynamicJsonDocument *actionRequest = - new DynamicJsonDocument(SMALL_JSON_DOCUMENT_SIZE); - - JsonObject actionObj = actionRequest->to(); - JsonObject nested = actionObj.createNestedObject(kv.key()); - - for (JsonPair kvInner : kv.value().as()) { - nested[kvInner.key()] = kvInner.value(); - } - - ThingActionObject *obj = device->requestAction(actionRequest); - if (obj != nullptr) { - obj->setNotifyFunction(std::bind(&ThingDevice::sendActionStatus, - device, std::placeholders::_1)); - device->sendActionStatus(obj); - - obj->start(); - } - } - } else if (messageType == "addEventSubscription") { - for (JsonPair kv : data) { - ThingEvent *event = device->findEvent(kv.key().c_str()); - if (event) { - device->addEventSubscription(client->id(), event->id); - } - } - } - } - - void sendChangedProperties(ThingDevice *device) { - // Prepare one buffer per device - DynamicJsonDocument message(LARGE_JSON_DOCUMENT_SIZE); - message["messageType"] = "propertyStatus"; - JsonObject prop = message.createNestedObject("data"); - bool dataToSend = false; - ThingItem *item = device->firstProperty; - while (item != nullptr) { - ThingDataValue *value = item->changedValueOrNull(); - if (value) { - dataToSend = true; - item->serializeValue(prop); - } - item = item->next; - } - if (dataToSend) { - String jsonStr; - serializeJson(message, jsonStr); - // Inform all connected ws clients of a Thing about changed properties - ((AsyncWebSocket *)device->ws)->textAll(jsonStr); - } - } -#endif - void handleUnknown(AsyncWebServerRequest *request) { if (!verifyHost(request)) { return; @@ -513,11 +379,6 @@ class WebThingAdapter { return; } -#ifndef WITHOUT_WS - obj->setNotifyFunction(std::bind(&ThingDevice::sendActionStatus, device, - std::placeholders::_1)); -#endif - DynamicJsonDocument respBuffer(SMALL_JSON_DOCUMENT_SIZE); JsonObject item = respBuffer.to(); obj->serialize(item, device->id); @@ -624,11 +485,6 @@ class WebThingAdapter { return; } -#ifndef WITHOUT_WS - obj->setNotifyFunction(std::bind(&ThingDevice::sendActionStatus, device, - std::placeholders::_1)); -#endif - DynamicJsonDocument respBuffer(SMALL_JSON_DOCUMENT_SIZE); JsonObject item = respBuffer.to(); obj->serialize(item, device->id); diff --git a/Thing.h b/Thing.h index a9cd53e..9aa6731 100644 --- a/Thing.h +++ b/Thing.h @@ -54,10 +54,6 @@ class ThingActionObject { void (*start_fn)(const JsonVariant &); void (*cancel_fn)(); -#ifndef WITHOUT_WS - std::function notify_fn; -#endif - public: String name; DynamicJsonDocument *actionRequest = nullptr; @@ -76,12 +72,6 @@ class ThingActionObject { generateId(); } -#ifndef WITHOUT_WS - void setNotifyFunction(std::function notify_fn_) { - notify_fn = notify_fn_; - } -#endif - void generateId() { for (uint8_t i = 0; i < 16; ++i) { char c = (char)random('0', 'g'); @@ -115,11 +105,6 @@ class ThingActionObject { void setStatus(const char *s) { status = s; -#ifndef WITHOUT_WS - if (notify_fn != nullptr) { - notify_fn(this); - } -#endif } void start() { @@ -361,67 +346,7 @@ class ThingProperty : public ThingItem { } } }; - -#ifndef WITHOUT_WS -class EventSubscription { -public: - uint32_t id; - EventSubscription *next; - - EventSubscription(uint32_t id_) : id(id_) {} -}; - -class ThingEvent : public ThingItem { -private: - EventSubscription *subscriptions = nullptr; - -public: - ThingEvent(const char *id_, const char *description_, ThingDataType type_, - const char *atType_) - : ThingItem(id_, description_, type_, atType_) {} - - void addSubscription(uint32_t id) { - EventSubscription *sub = new EventSubscription(id); - sub->next = subscriptions; - subscriptions = sub; - } - - void removeSubscription(uint32_t id) { - EventSubscription *curr = subscriptions; - EventSubscription *prev = nullptr; - while (curr != nullptr) { - if (curr->id == id) { - if (prev == nullptr) { - subscriptions = curr->next; - } else { - prev->next = curr->next; - } - - delete curr; - return; - } - - prev = curr; - curr = curr->next; - } - } - - bool isSubscribed(uint32_t id) { - EventSubscription *curr = subscriptions; - while (curr != nullptr) { - if (curr->id == id) { - return true; - } - - curr = curr->next; - } - - return false; - } -}; -#else using ThingEvent = ThingItem; -#endif class ThingEventObject { public: @@ -471,9 +396,6 @@ class ThingDevice { String title; String description; const char **type; -#if !defined(WITHOUT_WS) && (defined(ESP8266) || defined(ESP32)) - AsyncWebSocket *ws = nullptr; -#endif ThingDevice *next = nullptr; ThingProperty *firstProperty = nullptr; ThingAction *firstAction = nullptr; @@ -485,42 +407,8 @@ class ThingDevice { : id(_id), title(_title), type(_type) {} ~ThingDevice() { -#if !defined(WITHOUT_WS) && (defined(ESP8266) || defined(ESP32)) - if (ws) - delete ws; -#endif - } - -#ifndef WITHOUT_WS - void removeEventSubscriptions(uint32_t id) { - ThingEvent *event = firstEvent; - while (event != nullptr) { - event->removeSubscription(id); - event = (ThingEvent *)event->next; - } - } - - void addEventSubscription(uint32_t id, String eventName) { - ThingEvent *event = findEvent(eventName.c_str()); - if (!event) { - return; - } - - event->addSubscription(id); } - void sendActionStatus(ThingActionObject *action) { - DynamicJsonDocument message(LARGE_JSON_DOCUMENT_SIZE); - message["messageType"] = "actionStatus"; - JsonObject prop = message.createNestedObject("data"); - action->serialize(prop, id); - String jsonStr; - serializeJson(message, jsonStr); - // Inform all connected ws clients about action statuses - ((AsyncWebSocket *)ws)->textAll(jsonStr); - } -#endif - ThingProperty *findProperty(const char *id) { ThingProperty *p = this->firstProperty; while (p) { @@ -668,31 +556,6 @@ class ThingDevice { void queueEventObject(ThingEventObject *obj) { obj->next = eventQueue; eventQueue = obj; - -#ifndef WITHOUT_WS - ThingEvent *event = findEvent(obj->name.c_str()); - if (!event) { - return; - } - - // * Send events as defined in "4.7 event message" - DynamicJsonDocument message(SMALL_JSON_DOCUMENT_SIZE); - message["messageType"] = "event"; - JsonObject data = message.createNestedObject("data"); - obj->serialize(data); - String jsonStr; - serializeJson(message, jsonStr); - - // Inform all subscribed ws clients about events - for (AsyncWebSocketClient *client : - ((AsyncWebSocket *)this->ws)->getClients()) { - uint32_t id = client->id(); - - if (event->isSubscribed(id)) { - ((AsyncWebSocket *)this->ws)->text(id, jsonStr); - } - } -#endif } void serialize(JsonObject descr, String ip, uint16_t port) { @@ -742,22 +605,6 @@ class ThingDevice { } */ -#ifndef WITHOUT_WS - { - JsonObject links_prop = links.createNestedObject(); - //links_prop["rel"] = "alternate"; - - if (port != 80) { - char buffer[33]; - itoa(port, buffer, 10); - links_prop["href"] = - "ws://" + ip + ":" + buffer + "/things/" + this->id; - } else { - links_prop["href"] = "ws://" + ip + "/things/" + this->id; - } - } -#endif - ThingProperty *property = this->firstProperty; if (property != nullptr) { JsonObject properties = descr.createNestedObject("properties"); From 30ebfd7971703af663ee3bf51900a453ddcf5915 Mon Sep 17 00:00:00 2001 From: Citrullin Date: Thu, 12 Aug 2021 15:10:07 +0200 Subject: [PATCH 06/13] Move TD to /.well-known/wot-thing-description --- ESPWebThingAdapter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ESPWebThingAdapter.h b/ESPWebThingAdapter.h index cbe76b4..166f6dc 100644 --- a/ESPWebThingAdapter.h +++ b/ESPWebThingAdapter.h @@ -55,7 +55,7 @@ class WebThingAdapter { } MDNS.addService("webthing", "tcp", port); - MDNS.addServiceTxt("webthing", "tcp", "path", "/"); + MDNS.addServiceTxt("webthing", "tcp", "path", "/.well-known/wot-thing-description"); DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); DefaultHeaders::Instance().addHeader("Access-Control-Allow-Methods", @@ -70,7 +70,7 @@ class WebThingAdapter { this->server.on("/*", HTTP_OPTIONS, std::bind(&WebThingAdapter::handleOptions, this, std::placeholders::_1)); - this->server.on("/", HTTP_GET, + this->server.on("/.well-known/wot-thing-description", HTTP_GET, std::bind(&WebThingAdapter::handleThings, this, std::placeholders::_1)); From 53d9023eb4072609adb6b9743b1b2066fda9c0f1 Mon Sep 17 00:00:00 2001 From: Citrullin Date: Thu, 12 Aug 2021 15:11:14 +0200 Subject: [PATCH 07/13] Remove things array around TD --- ESPWebThingAdapter.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ESPWebThingAdapter.h b/ESPWebThingAdapter.h index 166f6dc..9cf9320 100644 --- a/ESPWebThingAdapter.h +++ b/ESPWebThingAdapter.h @@ -228,16 +228,15 @@ class WebThingAdapter { request->beginResponseStream("application/json"); DynamicJsonDocument buf(LARGE_JSON_DOCUMENT_SIZE); - JsonArray things = buf.to(); + JsonObject thing = buf.to(); ThingDevice *device = this->firstDevice; while (device != nullptr) { - JsonObject descr = things.createNestedObject(); - device->serialize(descr, ip, port); - descr["href"] = "/things/" + device->id; + device->serialize(thing, ip, port); + thing["href"] = "/things/" + device->id; device = device->next; } - serializeJson(things, *response); + serializeJson(thing, *response); request->send(response); } From 924fe56c599a31767ea184cd23778322821a2df6 Mon Sep 17 00:00:00 2001 From: Citrullin Date: Tue, 17 Aug 2021 09:15:18 +0200 Subject: [PATCH 08/13] Remove commented out code --- Thing.h | 2 -- WiFi101WebThingAdapter.h | 26 ++------------------------ 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/Thing.h b/Thing.h index 9aa6731..6955618 100644 --- a/Thing.h +++ b/Thing.h @@ -385,8 +385,6 @@ class ThingEventObject { data["data"] = *this->getValue().string; break; } - - //data["timestamp"] = timestamp; } }; diff --git a/WiFi101WebThingAdapter.h b/WiFi101WebThingAdapter.h index e07b528..4a2cee3 100644 --- a/WiFi101WebThingAdapter.h +++ b/WiFi101WebThingAdapter.h @@ -308,30 +308,8 @@ class WebThingAdapter { handleError(); } return; - } /*else if (uri == deviceBase + "/properties") { - if (method == HTTP_GET || method == HTTP_OPTIONS) { - handleThingPropertiesGet(device->firstProperty); - } else { - handleError(); - } - return; - } else if (uri == deviceBase + "/actions") { - if (method == HTTP_GET || method == HTTP_OPTIONS) { - handleThingActionsGet(device); - } else if (method == HTTP_POST) { - handleThingActionsPost(device); - } else { - handleError(); - } - return; - } else if (uri == deviceBase + "/events") { - if (method == HTTP_GET || method == HTTP_OPTIONS) { - handleThingEventsGet(device); - } else { - handleError(); - } - return;*/ - } else { + } + } else { ThingProperty *property = device->firstProperty; while (property != nullptr) { String propertyBase = deviceBase + "/properties/" + property->id; From 1a674fa730659354d60c44ea8a02e4dc7b3d0888 Mon Sep 17 00:00:00 2001 From: Citrullin Date: Tue, 17 Aug 2021 09:25:05 +0200 Subject: [PATCH 09/13] Add w3c td v1 and webthings context --- Thing.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Thing.h b/Thing.h index 6955618..8febfa6 100644 --- a/Thing.h +++ b/Thing.h @@ -559,7 +559,9 @@ class ThingDevice { void serialize(JsonObject descr, String ip, uint16_t port) { descr["id"] = this->id; descr["title"] = this->title; - descr["@context"] = " https://www.w3.org/2019/wot/td/v1"; + JsonArray context = descr.createNestedArray("@context"); + context.add("https://www.w3.org./2019/wot/td/v1"); + context.add("https://webthings.io/schemas"); if (this->description != "") { descr["description"] = this->description; From 123a053c05bd9c6087eab59148de803673e895e1 Mon Sep 17 00:00:00 2001 From: Citrullin Date: Tue, 17 Aug 2021 09:42:14 +0200 Subject: [PATCH 10/13] Add things->forms for properties --- Thing.h | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/Thing.h b/Thing.h index 8febfa6..1e66e77 100644 --- a/Thing.h +++ b/Thing.h @@ -586,24 +586,17 @@ class ThingDevice { typeJson.add(*type); type++; } - /* - JsonArray links = descr.createNestedArray("forms"); + + JsonArray forms = descr.createNestedArray("forms"); { - JsonObject links_prop = links.createNestedObject(); - links_prop["href"] = "/things/" + this->id + "/properties"; + JsonObject forms_prop = forms.createNestedObject(); + forms_prop["rel"] = "properties"; + JsonArray context = forms_prop.createNestedArray("op"); + context.add("readallproperties"); + context.add("writeallproperties"); + forms_prop["href"] = "/things/" + this->id + "/properties"; } - { - JsonObject links_prop = links.createNestedObject(); - links_prop["href"] = "/things/" + this->id + "/actions"; - } - - { - JsonObject links_prop = links.createNestedObject(); - links_prop["rel"] = "events"; - links_prop["href"] = "/things/" + this->id + "/events"; - } - */ ThingProperty *property = this->firstProperty; if (property != nullptr) { From d5511fc0e8a18f3edf54cbe316cff0d45e12573b Mon Sep 17 00:00:00 2001 From: Citrullin Date: Tue, 17 Aug 2021 23:12:16 +0200 Subject: [PATCH 11/13] Remove Wifi101 --- WebThingAdapter.h | 1 - WiFi101WebThingAdapter.h | 663 --------------------------------------- 2 files changed, 664 deletions(-) delete mode 100644 WiFi101WebThingAdapter.h diff --git a/WebThingAdapter.h b/WebThingAdapter.h index 2d72fa8..cb76ac8 100644 --- a/WebThingAdapter.h +++ b/WebThingAdapter.h @@ -11,4 +11,3 @@ #pragma once #include "ESPWebThingAdapter.h" -#include "WiFi101WebThingAdapter.h" diff --git a/WiFi101WebThingAdapter.h b/WiFi101WebThingAdapter.h deleted file mode 100644 index 4a2cee3..0000000 --- a/WiFi101WebThingAdapter.h +++ /dev/null @@ -1,663 +0,0 @@ -/** - * WiFi101WebThingAdapter.h - * - * Exposes the Web Thing API based on provided ThingDevices. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#if !defined(ESP32) && !defined(ESP8266) - -#include - -#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) -#include -#else -#include -#endif - -#include -#include - -#include - -#define WITHOUT_WS 1 -#include "Thing.h" - -#ifndef LARGE_JSON_DOCUMENT_SIZE -#ifdef LARGE_JSON_BUFFERS -#define LARGE_JSON_DOCUMENT_SIZE 4096 -#else -#define LARGE_JSON_DOCUMENT_SIZE 1024 -#endif -#endif - -#ifndef SMALL_JSON_DOCUMENT_SIZE -#ifdef LARGE_JSON_BUFFERS -#define SMALL_JSON_DOCUMENT_SIZE 1024 -#else -#define SMALL_JSON_DOCUMENT_SIZE 256 -#endif -#endif - -static const bool DEBUG = false; - -enum HTTPMethod { - HTTP_ANY, - HTTP_GET, - HTTP_PUT, - HTTP_POST, - HTTP_DELETE, - HTTP_OPTIONS -}; - -enum ReadState { - STATE_READ_METHOD, - STATE_READ_URI, - STATE_DISCARD_HTTP11, - STATE_DISCARD_HEADERS_PRE_HOST, - STATE_READ_HOST, - STATE_DISCARD_HEADERS_POST_HOST, - STATE_READ_CONTENT -}; - -class WebThingAdapter { -public: - WebThingAdapter(String _name, uint32_t _ip, uint16_t _port = 80, - bool _disableHostValidation = false) - : name(_name), port(_port), server(_port), - disableHostValidation(_disableHostValidation), mdns(udp) { - ip = ""; - for (int i = 0; i < 4; i++) { - ip += _ip & 0xff; - if (i < 3) { - ip += '.'; - } - _ip >>= 8; - } - } - - void begin() { - name.toLowerCase(); - - String serviceName = name + "._webthing"; - mdns.begin(WiFi.localIP(), name.c_str()); - // \x06 is the length of the record - mdns.addServiceRecord(serviceName.c_str(), port, MDNSServiceTCP, - "\x06path=/"); - - server.begin(); - } - - void update() { - mdns.run(); - - if (!client) { - WiFiClient client = server.available(); - if (!client) { - return; - } - if (DEBUG) { - Serial.println("New client available"); - } - this->client = client; - } - - if (!client.connected()) { - if (DEBUG) { - Serial.println("Client disconnected"); - } - resetParser(); - client.stop(); - return; - } - - char c = client.read(); - if (c == 255 || c == -1) { - if (state == STATE_READ_CONTENT) { - handleRequest(); - resetParser(); - } - - retries += 1; - if (retries > 5000) { - if (DEBUG) { - Serial.println("Giving up on client"); - } - resetParser(); - client.stop(); - } - return; - } - - switch (state) { - case STATE_READ_METHOD: - if (c == ' ') { - if (methodRaw == "GET") { - method = HTTP_GET; - } else if (methodRaw == "POST") { - method = HTTP_POST; - } else if (methodRaw == "PUT") { - method = HTTP_PUT; - } else if (methodRaw == "DELETE") { - method = HTTP_DELETE; - } else if (methodRaw == "OPTIONS") { - method = HTTP_OPTIONS; - } else { - method = HTTP_ANY; - } - state = STATE_READ_URI; - } else { - methodRaw += c; - } - break; - - case STATE_READ_URI: - if (c == ' ') { - state = STATE_DISCARD_HTTP11; - } else { - uri += c; - } - break; - - case STATE_DISCARD_HTTP11: - if (c == '\r') { - state = STATE_DISCARD_HEADERS_PRE_HOST; - } - break; - - case STATE_DISCARD_HEADERS_PRE_HOST: - if (c == '\r') { - break; - } - if (c == '\n') { - headerRaw = ""; - break; - } - if (c == ':') { - if (headerRaw.equalsIgnoreCase("Host")) { - state = STATE_READ_HOST; - } - break; - } - - headerRaw += c; - break; - - case STATE_READ_HOST: - if (c == '\r') { - returnsAndNewlines = 1; - state = STATE_DISCARD_HEADERS_POST_HOST; - break; - } - if (c == ' ') { - break; - } - host += c; - break; - - case STATE_DISCARD_HEADERS_POST_HOST: - if (c == '\r' || c == '\n') { - returnsAndNewlines += 1; - } else { - returnsAndNewlines = 0; - } - if (returnsAndNewlines == 4) { - state = STATE_READ_CONTENT; - } - break; - - case STATE_READ_CONTENT: - content += c; - break; - } - } - - void addDevice(ThingDevice *device) { - if (this->lastDevice == nullptr) { - this->firstDevice = device; - this->lastDevice = device; - } else { - this->lastDevice->next = device; - this->lastDevice = device; - } - } - -private: - String name, ip; - uint16_t port; - bool disableHostValidation; - WiFiServer server; - WiFiClient client; - WiFiUDP udp; - MDNS mdns; - - ReadState state = STATE_READ_METHOD; - String uri = ""; - HTTPMethod method = HTTP_ANY; - String content = ""; - String methodRaw = ""; - String host = ""; - String headerRaw = ""; - int returnsAndNewlines = 0; - int retries = 0; - - ThingDevice *firstDevice = nullptr, *lastDevice = nullptr; - - bool verifyHost() { - if (disableHostValidation) { - return true; - } - - int colonIndex = host.indexOf(':'); - if (colonIndex >= 0) { - host.remove(colonIndex); - } - if (host.equalsIgnoreCase(name + ".local")) { - return true; - } - if (host == ip) { - return true; - } - if (host == "localhost") { - return true; - } - return false; - } - - void handleRequest() { - if (DEBUG) { - Serial.print("handleRequest: "); - Serial.print("method: "); - Serial.println(method); - Serial.print("uri: "); - Serial.println(uri); - Serial.print("host: "); - Serial.println(host); - Serial.print("content: "); - Serial.println(content); - } - - if (!verifyHost()) { - client.println("HTTP/1.1 403 Forbidden"); - client.println("Connection: close"); - client.println(); - delay(1); - client.stop(); - return; - } - - if (uri == "/") { - handleThings(); - return; - } - - ThingDevice *device = this->firstDevice; - while (device != nullptr) { - String deviceBase = "/things/" + device->id; - - if (uri.startsWith(deviceBase)) { - if (uri == deviceBase) { - if (method == HTTP_GET || method == HTTP_OPTIONS) { - handleThing(device); - } else { - handleError(); - } - return; - } - } else { - ThingProperty *property = device->firstProperty; - while (property != nullptr) { - String propertyBase = deviceBase + "/properties/" + property->id; - if (uri == propertyBase) { - if (method == HTTP_GET || method == HTTP_OPTIONS) { - handleThingPropertyGet(property); - } else if (method == HTTP_PUT) { - handleThingPropertyPut(device, property); - } else { - handleError(); - } - return; - } - property = (ThingProperty *)property->next; - } - - ThingAction *action = device->firstAction; - while (action != nullptr) { - String actionBase = deviceBase + "/actions/" + action->id; - if (uri == actionBase) { - if (method == HTTP_GET || method == HTTP_OPTIONS) { - handleThingActionGet(device, action); - } else if (method == HTTP_POST) { - handleThingActionPost(device, action); - } else { - handleError(); - } - return; - } else if (uri.startsWith(actionBase + "/") && - uri.length() > (actionBase.length() + 1)) { - if (method == HTTP_GET || method == HTTP_OPTIONS) { - handleThingActionIdGet(device, action); - } else if (method == HTTP_DELETE) { - handleThingActionIdDelete(device, action); - } else { - handleError(); - } - return; - } - action = action->next; - } - - ThingEvent *event = device->firstEvent; - while (event != nullptr) { - String eventBase = deviceBase + "/events/" + event->id; - if (uri == eventBase) { - if (method == HTTP_GET || method == HTTP_OPTIONS) { - handleThingEventGet(device, event); - } else { - handleError(); - } - return; - } - event = (ThingEvent *)event->next; - } - } - } - device = device->next; - } - handleError(); - } - - void sendOk() { client.println("HTTP/1.1 200 OK"); } - - void sendCreated() { client.println("HTTP/1.1 201 Created"); } - - void sendNoContent() { client.println("HTTP/1.1 204 No Content"); } - - void sendHeaders() { - client.println("Access-Control-Allow-Origin: *"); - client.println( - "Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS"); - client.println("Access-Control-Allow-Headers: " - "Origin, X-Requested-With, Content-Type, Accept"); - client.println("Content-Type: application/json"); - client.println("Connection: close"); - client.println(); - } - - void handleThings() { - sendOk(); - sendHeaders(); - - DynamicJsonDocument buf(LARGE_JSON_DOCUMENT_SIZE); - JsonArray things = buf.to(); - ThingDevice *device = this->firstDevice; - while (device != nullptr) { - JsonObject descr = things.createNestedObject(); - device->serialize(descr, ip, port); - descr["href"] = "/things/" + device->id; - device = device->next; - } - - serializeJson(things, client); - delay(1); - client.stop(); - } - - void handleThing(ThingDevice *device) { - sendOk(); - sendHeaders(); - - DynamicJsonDocument buf(LARGE_JSON_DOCUMENT_SIZE); - JsonObject descr = buf.to(); - device->serialize(descr, ip, port); - - serializeJson(descr, client); - delay(1); - client.stop(); - } - - void handleThingPropertyGet(ThingItem *item) { - sendOk(); - sendHeaders(); - - DynamicJsonDocument doc(SMALL_JSON_DOCUMENT_SIZE); - JsonObject prop = doc.to(); - item->serializeValue(prop); - serializeJson(prop, client); - delay(1); - client.stop(); - } - - void handleThingActionGet(ThingDevice *device, ThingAction *action) { - sendOk(); - sendHeaders(); - - DynamicJsonDocument doc(LARGE_JSON_DOCUMENT_SIZE); - JsonArray queue = doc.to(); - device->serializeActionQueue(queue, action->id); - serializeJson(queue, client); - delay(1); - client.stop(); - } - - void handleThingActionIdGet(ThingDevice *device, ThingAction *action) { - String base = "/things/" + device->id + "/actions/" + action->id; - String actionId = uri.substring(base.length() + 1); - const char *actionIdC = actionId.c_str(); - const char *slash = strchr(actionIdC, '/'); - - if (slash) { - actionId = actionId.substring(0, slash - actionIdC); - } - - ThingActionObject *obj = device->findActionObject(actionId.c_str()); - if (obj == nullptr) { - handleError(); - return; - } - - sendOk(); - sendHeaders(); - - DynamicJsonDocument doc(SMALL_JSON_DOCUMENT_SIZE); - JsonObject o = doc.to(); - obj->serialize(o, device->id); - serializeJson(o, client); - delay(1); - client.stop(); - } - - void handleThingActionIdDelete(ThingDevice *device, ThingAction *action) { - String base = "/things/" + device->id + "/actions/" + action->id; - String actionId = uri.substring(base.length() + 1); - const char *actionIdC = actionId.c_str(); - const char *slash = strchr(actionIdC, '/'); - - if (slash) { - actionId = actionId.substring(0, slash - actionIdC); - } - - device->removeAction(actionId); - sendNoContent(); - sendHeaders(); - } - - void handleThingActionPost(ThingDevice *device, ThingAction *action) { - DynamicJsonDocument *newBuffer = - new DynamicJsonDocument(SMALL_JSON_DOCUMENT_SIZE); - auto error = deserializeJson(*newBuffer, content); - if (error) { // unable to parse json - handleError(); - delete newBuffer; - return; - } - - JsonObject newAction = newBuffer->as(); - - if (!newAction.containsKey(action->id)) { - handleError(); - delete newBuffer; - return; - } - - ThingActionObject *obj = device->requestAction(newBuffer); - - if (obj == nullptr) { - handleError(); - delete newBuffer; - return; - } - - sendCreated(); - sendHeaders(); - - DynamicJsonDocument respBuffer(SMALL_JSON_DOCUMENT_SIZE); - JsonObject item = respBuffer.to(); - obj->serialize(item, device->id); - serializeJson(item, client); - delay(1); - client.stop(); - - obj->start(); - } - - void handleThingEventGet(ThingDevice *device, ThingItem *item) { - sendOk(); - sendHeaders(); - - DynamicJsonDocument doc(SMALL_JSON_DOCUMENT_SIZE); - JsonArray queue = doc.to(); - device->serializeEventQueue(queue, item->id); - serializeJson(queue, client); - delay(1); - client.stop(); - } - - void handleThingPropertiesGet(ThingItem *rootItem) { - sendOk(); - sendHeaders(); - - DynamicJsonDocument doc(LARGE_JSON_DOCUMENT_SIZE); - JsonObject prop = doc.to(); - ThingItem *item = rootItem; - while (item != nullptr) { - item->serializeValue(prop); - item = item->next; - } - serializeJson(prop, client); - delay(1); - client.stop(); - } - - void handleThingActionsGet(ThingDevice *device) { - sendOk(); - sendHeaders(); - - DynamicJsonDocument doc(LARGE_JSON_DOCUMENT_SIZE); - JsonArray queue = doc.to(); - device->serializeActionQueue(queue); - serializeJson(queue, client); - delay(1); - client.stop(); - } - - void handleThingActionsPost(ThingDevice *device) { - DynamicJsonDocument *newBuffer = - new DynamicJsonDocument(SMALL_JSON_DOCUMENT_SIZE); - auto error = deserializeJson(*newBuffer, content); - if (error) { // unable to parse json - handleError(); - delete newBuffer; - return; - } - - JsonObject newAction = newBuffer->as(); - - if (newAction.size() != 1) { - handleError(); - delete newBuffer; - return; - } - - ThingActionObject *obj = device->requestAction(newBuffer); - - if (obj == nullptr) { - handleError(); - delete newBuffer; - return; - } - - sendCreated(); - sendHeaders(); - - DynamicJsonDocument respBuffer(SMALL_JSON_DOCUMENT_SIZE); - JsonObject item = respBuffer.to(); - obj->serialize(item, device->id); - serializeJson(item, client); - delay(1); - client.stop(); - - obj->start(); - } - - void handleThingEventsGet(ThingDevice *device) { - sendOk(); - sendHeaders(); - - DynamicJsonDocument doc(LARGE_JSON_DOCUMENT_SIZE); - JsonArray queue = doc.to(); - device->serializeEventQueue(queue); - serializeJson(queue, client); - delay(1); - client.stop(); - } - - void handleThingPropertyPut(ThingDevice *device, ThingProperty *property) { - DynamicJsonDocument newBuffer(SMALL_JSON_DOCUMENT_SIZE); - auto error = deserializeJson(newBuffer, content); - if (error) { // unable to parse json - handleError(); - return; - } - JsonObject newProp = newBuffer.as(); - - if (!newProp.containsKey(property->id)) { - handleError(); - return; - } - - device->setProperty(property->id.c_str(), newProp[property->id]); - - sendOk(); - sendHeaders(); - - serializeJson(newProp, client); - delay(1); - client.stop(); - } - - void handleError() { - client.println("HTTP/1.1 400 Bad Request"); - sendHeaders(); - delay(1); - client.stop(); - } - - void resetParser() { - state = STATE_READ_METHOD; - method = HTTP_ANY; - methodRaw = ""; - headerRaw = ""; - host = ""; - uri = ""; - content = ""; - retries = 0; - } -}; - -#endif // neither ESP32 nor ESP8266 defined From 4f7a5a5bd7cb3adc7223ce4a57772510cd27c2c3 Mon Sep 17 00:00:00 2001 From: Citrullin Date: Tue, 17 Aug 2021 23:29:51 +0200 Subject: [PATCH 12/13] Update BPM280 example --- examples/BME280/BME280.ino | 121 +++++++++++++++---------------------- 1 file changed, 50 insertions(+), 71 deletions(-) diff --git a/examples/BME280/BME280.ino b/examples/BME280/BME280.ino index 60543fa..754ed34 100644 --- a/examples/BME280/BME280.ino +++ b/examples/BME280/BME280.ino @@ -1,32 +1,3 @@ -/* - WiFi Web Server LED control via web of things (e.g., WebThings Gateway) - based on WiFi101.h example "Provisioning_WiFiWebServer.ino" - - A simple web server that lets you control an LED via the web. - This sketch will print the IP address of your WiFi device (once connected) - to the Serial monitor. From there, you can open that address in a web browser - to turn on and off the onboard LED. - - You can also connect via the Things Gateway http-on-off-wifi-adapter. - - If the IP address of your shield is yourAddress: - http://yourAddress/H turns the LED on - http://yourAddress/L turns it off - - This example is written for a network using WPA encryption. For - WEP or WPA, change the Wifi.begin() call accordingly. - - Circuit: - * WiFi using Microchip (Atmel) WINC1500 - * LED attached to pin 1 (onboard LED) for SAMW25 - * LED attached to pin 6 for MKR1000 - - created 25 Nov 2012 - by Tom Igoe - - updates: dh, kg 2018 - */ - #define LARGE_JSON_BUFFERS 1 #include @@ -34,7 +5,7 @@ #include #include #include -#include +#include #include #include @@ -45,6 +16,18 @@ #define PIN_STATE_LOW LOW #endif +#define ESP32 + +// TODO: Hardcode your wifi credentials here (and keep it private) +const char *ssid = ""; +const char *password = ""; + +#if defined(LED_BUILTIN) +const int ledPin = LED_BUILTIN; +#else +const int ledPin = 13; // manually configure LED pin +#endif + WebThingAdapter *adapter; const char *bme280Types[] = {"TemperatureSensor", nullptr}; @@ -54,12 +37,16 @@ ThingProperty weatherTemp("temperature", "", NUMBER, "TemperatureProperty"); ThingProperty weatherHum("humidity", "", NUMBER, "LevelProperty"); ThingProperty weatherPres("pressure", "", NUMBER, nullptr); -BME280I2C::Settings - settings(BME280::OSR_X1, BME280::OSR_X1, BME280::OSR_X1, - BME280::Mode_Forced, BME280::StandbyTime_1000ms, - BME280::Filter_Off, BME280::SpiEnable_False, - (BME280I2C::I2CAddr)0x76 // I2C address. I2C specific. - ); +BME280I2C::Settings settings( + BME280::OSR_X1, + BME280::OSR_X1, + BME280::OSR_X1, + BME280::Mode_Forced, + BME280::StandbyTime_1000ms, + BME280::Filter_Off, + BME280::SpiEnable_False, + BME280I2C::I2CAddr_0x76 // I2C address. I2C specific. +); BME280I2C bme(settings); @@ -79,49 +66,41 @@ void readBME280Data() { } void setup() { - // Initialize serial: - // Serial.begin(9600); - - // check for the presence of the shield: - // Serial.print("Configuring WiFi shield/module...\n"); - if (WiFi.status() == WL_NO_SHIELD) { - // Serial.println("WiFi shield not present"); - // don't continue: - while (true) - ; + Serial.println("Initialize..."); + + pinMode(ledPin, OUTPUT); + digitalWrite(ledPin, HIGH); + Serial.begin(115200); + Serial.println(""); + Serial.print("Connecting to \""); + Serial.print(ssid); + Serial.println("\""); + WiFi.begin(ssid, password); + + bool blink = true; + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + digitalWrite(ledPin, blink ? LOW : HIGH); // active low led + blink = !blink; } + digitalWrite(ledPin, HIGH); // active low led - // configure the LED pin for output mode - pinMode(LED_BUILTIN, OUTPUT); + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); Wire.begin(); while (!bme.begin()) { - // Serial.println("Could not find BME280I2C sensor!"); + Serial.println("Could not find BME280I2C sensor!"); delay(1000); } - - // Serial.println("Starting in provisioning mode..."); - // Start in provisioning mode: - // 1) This will try to connect to a previously associated access point. - // 2) If this fails, an access point named "wifi101-XXXX" will be created, - // where XXXX - // is the last 4 digits of the boards MAC address. Once you are connected - // to the access point, you can configure an SSID and password by - // visiting http://wifi101/ - WiFi.beginProvision(); - - while (WiFi.status() != WL_CONNECTED) { - // wait while not connected - - // blink the led to show an unconnected status - digitalWrite(LED_BUILTIN, PIN_STATE_HIGH); - delay(500); - digitalWrite(LED_BUILTIN, PIN_STATE_LOW); - delay(500); - } + Serial.println("BME280I2C connected and initialized."); // connected, make the LED stay on - digitalWrite(LED_BUILTIN, PIN_STATE_HIGH); + //digitalWrite(LED_BUILTIN, PIN_STATE_HIGH); adapter = new WebThingAdapter("weathersensor", WiFi.localIP()); // Set unit for temperature @@ -154,4 +133,4 @@ void setup() { void loop() { readBME280Data(); adapter->update(); -} +} \ No newline at end of file From 7d15182657e05790ee92a2da461654c2e02e26d1 Mon Sep 17 00:00:00 2001 From: Citrullin Date: Wed, 18 Aug 2021 19:02:12 +0200 Subject: [PATCH 13/13] LED on when connected in bmp280 example --- examples/BME280/BME280.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/BME280/BME280.ino b/examples/BME280/BME280.ino index 754ed34..f019d5d 100644 --- a/examples/BME280/BME280.ino +++ b/examples/BME280/BME280.ino @@ -100,7 +100,7 @@ void setup() { Serial.println("BME280I2C connected and initialized."); // connected, make the LED stay on - //digitalWrite(LED_BUILTIN, PIN_STATE_HIGH); + digitalWrite(LED_BUILTIN, PIN_STATE_HIGH); adapter = new WebThingAdapter("weathersensor", WiFi.localIP()); // Set unit for temperature