Open prestoncarman opened 3 years ago
This was identified as a very valuable issue in June 2023, but we aren't sure how difficult it would be so we aren't making it a priority yet...
Sending a SMS message can be done for about a penny each. @je-foster helped come up with the following:
We've already set up oap.cs.wallawalla.edu to serve the Flutter application over HTTP (to avoid mixing HTTP with HTTPS since the device does not have room for HTTPS). We could have the device contact our server and send the current status every five minutes and an immediate notification on configuration changes or out-of-range observations.
We will start with something simple: When the pH target is changed the device will open a connection to oap.cs.wallawalla.edu:80
and send the following:
POST /api/1/alert HTTP/1.1\r\n
Host: oap.cs.wallawalla.edu\r\n
Connection: close\r\n
Content-Type: text/plain\r\n
Content-Length: 68\r\n
Tank 3 (90A2:DAFD:C238): Target pH changed from 8.125 to 8.250.\r\n
The server will respond with:
HTTP/1.1 200 OK
The server will send a text message to a hard-coded number (eventually configurable) with the message (perhaps prefixed with something along the lines of OAP device alert: "..."
, and will save the alert to a file with a name based on the IP address of the device (which may be shared if multiple devices are sharing a public IP address).
It would be nice if the message included a link to view the alert on the OAP server.
I've created accounts at: d7networks.com, messagebird.com, and clicksend.com and will investigate further. It looks like it costs $1-$2/month for a line and $0.01 to $0.02 for each message.
After further discussion we've revised the plan as follows:
Logging will be done with a severity (Debug, Info, Warning, Error, and Fatal). Normal data will be recorded as Info every minute. The following events will be a Warning: boot, receipt of slope data, and changes to EEPROM (which will include config changes and bad calibrations).
Logging will be written to a single log file with one line per event. The first four fields will be version (so the format can change), tank ID, severity (D/I/W/E/F), and timestamp (YYYY-MM-DD HH:MM:SS would be most useful, but seconds since some epoch would be more compact). The remaining fields will depend on the severity where Info will include current and target values and Warning will include uptime (to indicate a recent boot), MAC (in case multiple devices get the same tank ID), pH slope (which would not be visible elsewhere), and EEPROM data (to indicate config changes). Debug, Error, and Fatal will be free-text until we decide that more structured data is available and appropriate.
Another task will be added to the main event loop that will look at the logging file on the SD card for any unsent data and send it to the cloud (oap.cs.wallawalla.edu). The write offset can be cached but should be initialized to on boot by reading the actual value. Of course, the new value will need to be written each time it changes. An index to the beginning of the unsent data needs to be persistent and writing to EEPROM once a minute would use up the 100,000 write cycles in 70 days so that doesn't work very well. Instead, we will use the SD card as a record of the character offset of the sent data.
Note that an SD card also has a limited number of write cycles, perhaps much less than flash, but should use wear leveling to spread out the write cycles. Some notes on SD write cycles:
To minimize the blocking time we could write one line per loop.
The cloud host (oap.cs.wallawalla.edu) could be set in the .ino file (with the PushingBox device ID) so other users could use a different cloud host.
Does the SD card wear-level automatically when we keep rewriting the same file? I suspect so but haven’t found confirmation for the Arduino.
Another option is to request the read index from the OAP server on boot, and cache the response.
The idea of asking the server for the size is a good one and fits within the broader concept of decoupling—instead of "here is what I think you need", you ask "what would you like?" Following this model we could use the HTTP request methods as follows:
Each device can provide a log file name (the server would choose the root directory—possibly based on the IP address for the device so that different laboratories would be in different locations). A POST would append to the file while a HEAD would return the file size (either on startup or more frequently); note that the HEAD could return a 404 (file not found) which should be treated as an empty file. Because the device would use the current file size on the server to decide what to send next, the file name would need to be unique to the device (not shared among multiple devices). I suggest that the default be the MAC address and (for simplicity) that we not bother with wrapping (starting new files). We could add a filename to the .INO file (where an empty string means use the MAC address) so that the researcher could assign a unique name (possibly tied to the experiment and tank ID).
This should keep both the client and server quite simple. The server could then be extended to monitor the incoming log file to do alerts (and, separately, to provide graphing and other features now found in the Google Sheets monitoring of PushingBox).
When the tank is outside expected values, sent a message by e-mail or phone.