Harsch-Systems / node-red-contrib-pi-plates

Control Pi-Plates from Node-RED
Apache License 2.0
6 stars 7 forks source link

Logs errors regarding python process and missing packages #12

Closed tyler-stowell closed 3 years ago

tyler-stowell commented 3 years ago

After node-pi-plates is updated, the BASEplate.py function returns the status of the python process. This uses that information to let nodes log errors regarding the process, instead of silently failing.

mharsch commented 3 years ago

This addresses #10

tyler-stowell commented 3 years ago

The second commit fixes a couple of issues I discovered:

First of all, I realized that a plate was verified once for each node it was included in. So, if there are 3 nodes that share a plate, the plate would be verified three times. So, I switched verification to be something that happened when the plate was initialized, instead of when a node was initialized.

Secondly, the previous way that I designed status messages for the plates had a couple of issues. First of all, it gave messages to the user both when something went wrong ("invalid plate or input") and when things went well ("plate validated"). I realized that messages on success was a bad idea (it would clutter things up), so I removed them. Secondly, I made the error messages more specific. Previously, if anything went wrong, it would display the "invalid plate or input" message. Now, it displays "invalid plate" if it can't find the plate, "python process error" if there are any errors related to the process that communicates with node-red (missing pi-plates/pygame dependencies, missing python3, etc.), "invalid channel/plate type/relay" if any of the node configuration options are invalid, and "invalid input" if the node's input message is the wrong type.

The third commit was an attempt to solve issue #13. I didn't have 2 DAQC2 plates, so I wasn't able to replicate the exact issue, but I did notice two race conditions that could have caused it:

The first race condition was that it was possible for a node to be called before the plate has finished verifying. At the moment, this is solved by just ignoring any inputs that arrive before verification is finished. Every time I tested it, the plate is done verifying long before any inputs are able to arrive, but now it won't break anything if it somehow happens anyways.

The second race condition was much more difficult to solve. If the process attempted to verify the plate before the plate was on, it would save its state as invalid, which couldn't be changed until the flow was redeployed. To fix this, two things had to be changed:

First of all, because there is no way to verify that an invalid plate is actually invalid (there are a couple situations where the pi-plates library can mess up, or the plate could suddenly crash and restart), every time a message is sent to an invalid plate, it prints out the "invalid plate" message, discards the input, and then reattempts validation. I chose to attempt validation after the fact, because the alternative (trying to revalidate the plate, waiting while the message is being sent, and then continuing) would involve a synchronous wrapper of an asynchronous function, and could have significant detrimental effects on node-red's speed if a large number of messages were sent to an invalid plate. So, if something goes wrong and the process believes a valid plate is invalid, the worst scenario is it fails one input and then corrects itself and accepts inputs in the future.

Secondly, if the node-red process failed in verifying the plates, chances are the pi-plates library did the same. (The pi-plates library contains its own state information on connected plates). If the node-red process detects that a plate that it believed was invalid is actually present, it needs to make sure that information gets to the pi-plates library (sending a message to a plate the piplates library believes is invalid will crash the python process, which is bad). So, a new command called "ACTIVATE" is added to plate_io.py, which just serves to update the pi-plates library. This command is called whenever an invalid plate is recognized as valid.