Now that I finally have a working ESP-32 mcu connected to my pool controller, I have to disconnect it and bring it inside every time I want to make the slightest changes to the flow.
I found this statement from Peter earlier this year -- and I'm just wondering if this is something I'll be able to use in my project.
Sweet... I've added the missing nodes and imported the example flows. So is this "no httpserver!" a build problem or user error?
Looks like maybe I need to set up an http in
node on the /ota/firmware
endpoint?
I was trying to push the .bin file contents through MQTT and pass it directly to the ota-update
node, but I can't tell if that's the way it should work or not:
I'm convinced, @phoddie can answer this better than I do...
When using push mode with the OTA node, there must be an HTTP In node in the flow. The OTA node adds a route to that for the firmware upload. Let me know how that goes. If it works for you, I'll update the docs and example. Alternatively, it may be possible to have the nodered2mcu tool automatically add the required dependency when it sees an OTA node configured for push mode (requires some investigation -- but that would be the most developer friendly solution).
FWIW – I believe that originally it wasn't necessary to add the HTTP In explicitly because the module was always included in the build. That was removed as a default to minimize the code size.
Thanks for the clarification... I think I was confused by the presence of an input port, which I assumed would accept a payload
buffer containing the the new binary. Is there any technical reason why that could not work (other than it's not implemented that way ;*) ?
Reading through it more thoroughly I think the pull mode would be better for me anyway, so I am pursuing that.
Well, I'm hitting a dead-end using the "pull" mode, too...
# Break: mcu.deliver: cannot coerce undefined to object!
#0: mcu.deliver /home/srickus/develop/node-red-mcu-plugin/node-red-mcu/nodered.js:138
#1: (host)
XS abort: unhandled exception
# Break: C: xsDebugger!
#0: mcu.deliver /home/srickus/develop/node-red-mcu-plugin/node-red-mcu/nodered.js:138
#1: (host)
The code throwing the exception is this function:
129 static deliver() {
130 Timer.schedule(msgQueue.timer);
131
132 let current = msgQueue.first;
133 msgQueue.first = msgQueue.last = undefined;
134 while (current) {
135 const next = current._next, target = current._target;
136 delete current._next;
137 delete current._target;
138 target.receive(current, target.makeDone(current));
139 current = next;
140 }
141 }
Has anyone seen this? The error seems to indicate that target
is undefined.
This exception happens in the msg
processing queue - deep in the core of node-red-mcu
. That's logic a node usually isn't able to affect; very interesting though.
Can you share a flow that triggers this exception?
There is a technical reason: memory. There's a good chance that the firmware binary won't fit in the free memory (our physical memory!) of the ESP32. The OTA node writes the firmware image to flash as it arrives, to keep the RAM requirement to a minimum.
1 Like
Can you share the steps to reproduce this? Two pieces are important:
- The flow you are using on the MCU
- The flow or curl command or whatever you are using to push the firmware update.
Thanks!
So while I was trying to pare down my flows to something that you could use to debug, I think I may have found the issue -- it seems I overlooked the critical input msg.url
parameter:
Instead, I was passing the url in the payload :*(
I find the editor for the OTA update
node to be rather confusing -- if the one node has two different operating modes with different inputs, I think it needs to be more explicit as to which is being used... similar to the way the json
node has a choice of "actions" with options for each (and a selector for which field to use for the input value):
Although I'm not seeing the mcu errors anymore, the ota update is not calling back, so I have more digging to do. I'll be back later!
Ok, I thought I was making progress... but there is something missing in my deployed binary. Notice how the ota-update
node in "push" mode is not finding the http server on the device:
I'm seeing that same thing when trying to use the node in "pull" mode -- I added a console.log output to the ota-update.js
module,
56 const url = new URL(msg.url);
57 if ("http:" !== url.protocol)
58 return void done("http only");
59 const options = {
60 ...device.network.http,
61 host: url.hostname
62 };
63 if (url.port)
64 options.port = parseInt(url.port);
65 console.log(device.network.http)
66 this.#client = new device.network.http.io(options);
The xsbug-log output shows that device.network.http
object is undefined:
# starting xsbug
#xsbug-log listening on port 5002. ^C to exit.
#xsbug-log connected to "main"
Wi-Fi connected to "S&J-Poolhouse"
IP address 192.168.1.107
<info>{"payload":0,"topic":"WROVER/GPIO/18","_msgid":"dcb636228a4f0edf","source":{"id":"e9bc691dd336e8e5","type":"debug","name":"RPi-4 debug"}}
undefined
# Break: OTAUpdateNode.prototype.onMessage: cannot coerce undefined to object!
#0: OTAUpdateNode.prototype.onMessage /home/srickus/develop/node-red-mcu-plugin/node-red-mcu/nodes/ota-update/ota-update.js:66
#1: Node.prototype.receive /home/srickus/develop/node-red-mcu-plugin/node-red-mcu/nodered.js:383
#2: mcu.deliver /home/srickus/develop/node-red-mcu-plugin/node-red-mcu/nodered.js:138
#3: (host)
XS abort: unhandled exception
Any idea why my build is not including the network http module?
__
Steve
Can someone explain to me how the device
object is defined/initialized?
(I guess I'm asking either @phoddie or @ralphwetzel) ...
The device
global specified by ECMA-419 as the host provider instance. It is created by including the $(MODDABLE)/modules/io/manifest.json
manifest in a project. It can be extended by other manifests during the build. For example, the HTTP client adds itself to device
.
Any idea why my build is not including the network http module?
Yes, it was originally included as part of the core of Node-RED MCU. At some point, the core was minimized to shrink binary sizes and speed install. Unfortunately, the OTA node wasn't updated. I did that yesterday If you grab the latest Node-RED MCU repository, both the HTTP client and HTTP server are now included by the OTA node. It should again work normally.
1 Like
I've pulled the latest code with the new included modules, but it seems to make no difference:
undefined
# Break: OTAUpdateNode.prototype.onMessage: cannot coerce undefined to object!
#0: OTAUpdateNode.prototype.onMessage /home/srickus/develop/node-red-mcu-plugin/node-red-mcu/nodes/ota-update/ota-update.js:66
#1: Node.prototype.receive /home/srickus/develop/node-red-mcu-plugin/node-red-mcu/nodered.js:383
#2: mcu.deliver /home/srickus/develop/node-red-mcu-plugin/node-red-mcu/nodered.js:138
#3: (host)
XS abort: unhandled exception
The line #66 is trying to create a new device.network.http.io(...)
-- but in other parts of the code I see references to device.io.xxx
... could this be a typo?
I'm still trying to wrap my head around how all of these technologies are working together -- can you show me where in the code this module extension is being executed?
I didn't commit the change until I had independent confirmation that the change was working. So, it can work. My guess is that you aren't actually running it. That might be my mistake. I pushed to the Node-RED MCU repo but I didn't update the module on npm used from the Node-RED Library. Can you confirm that you installed the OTA module from the Node-RED Library? If not, how did you install it? Thanks.
Update: version 0.8.7 of the ota-update module is live with the manifest change.
I have cloned the node-red-mcu
project to my local disk, and then npm install
ed it using the local file path. So node-red should be using it directly, and whenever git pull retrieves a new file I just restart node-red.
I did compare the newly pulled version of the manifest to my stashed version to see what you had to change:
[Mon 05:46:31 PM]
srickus@ shrpi4: ~/develop/node-red-mcu
$ git status
On branch main
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
Untracked files:
(use "git add <file>..." to include in what will be committed)
package-lock.json
nothing added to commit but untracked files present (use "git add" to track)
[Mon 05:46:44 PM]
srickus@ shrpi4: ~/develop/node-red-mcu
$ git pull
Updating d445b50..efd9062
Fast-forward
nodes/ota-update/manifest.json | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
[Mon 09:39:56 PM]
srickus@ shrpi4: ~/develop/node-red-mcu
$ git diff stash@{0}
diff --git a/nodes/ota-update/manifest.json b/nodes/ota-update/manifest.json
index 3cebfcb..7018f37 100644
--- a/nodes/ota-update/manifest.json
+++ b/nodes/ota-update/manifest.json
@@ -1,7 +1,8 @@
{
"include": [
"$(MODDABLE)/modules/data/url/manifest.json",
- "$(MODDABLE)/modules/network/http/manifest.json"
+ "$(MODDABLE)/examples/io/tcp/httpclient/manifest_httpclient.json",
+ "../network/httpserver/manifest.json"
],
"modules": {
"*": "./ota-update"
So I'm fairly sure I'm using the new code... and I ran a clean build to make sure my new binary was up to date.
Ok, I've rebuilt the npm modules, and am now using the newly updated ota-update@0.8.7
-- and now the build is a missing manifest file:
idf.py build
>> IDF_PYTHON_ENV_PATH: /home/srickus/develop/esp32/esp-idf/tools/python_env/idf5.1_py3.10_env
>> mcconfig -d -x localhost:5004 -l -m -p esp32
# warning: -l deprecated. use -dl instead.!
### Error: '../network/httpserver/manifest.json': manifest not found!
I guess that path is different under the npm repo than under node-red-mcu/nodes?
Oh.... if you are running from the library that relative path can't resolve. Try replacing the line with "$(NODEREDMCU)/nodes/network/httpserver/manifest.json"
. That should always work.
FYI – I've committed the change to use the absolute $(NODEREDMCU)... path instead of the relative path. That is now in ota-update@0.8.8
and also in the Node-RED MCU repo.
1 Like