jneilliii / OctoPrint-PlotlyTempGraph

23 stars 7 forks source link

Custom sensor plotted at previous value when 0 #47

Closed ScottWell1 closed 1 year ago

ScottWell1 commented 1 year ago

I created custom sensors using the example "SystemCmdMultiGraph.py" file. The bash scripts called return an integer between 0 and 100. That works; the sensors are listed in the PlotlyTempGraph settings panel, and the values are plotted on the chart.

However.... If the returned value changes to 0, the plotted value does not change to 0. It continues to be plotted at the last non-zero value. For example, if it last returned 50 before returning 0, the plotted value continues to be 50.

Is this a problem in the PlotlyTempGraph plugin code? Or should I be communicating the 0 value differently from the custom sensor?

jneilliii commented 1 year ago

It may be a random logic error in the plugin. Will have to investigate further as I always tested with random number generator above 0.

ScottWell1 commented 1 year ago

I always tested with random number generator above 0.

Understandable, no reason to expect any temperature values to ever hit 0! Appreciate you looking into it, thank you.

ScottWell1 commented 1 year ago

Just a clarification on the 0-values behaviors I am seeing:

ScottWell1 commented 1 year ago

One other thought….

The current behavior of suppressing 0-values likely has a benefit. For example, I suspect some M105 reports include chamber temp even though they don’t have a chamber - and suppressing the 0-values keeps those off the chart automatically. There are probably other, similar cases depending on the firmware.

So, any display of 0-values would probably need to be a new option to avoid impacting existing installations.

jneilliii commented 1 year ago

Curious if you could test an older version of the plugin for me. This will help identify if it was related to the Fahrenheit conversion stuff that I added or not. In plugin manager copy/paste the URL below into plugin manager > get more > ...from URL. and click install.

https://github.com/jneilliii/OctoPrint-PlotlyTempGraph/archive/refs/tags/0.1.3.zip
ScottWell1 commented 1 year ago

That test did not go well. :-)

I installed 0.1.3, and the temperature tab is non-functional. No graph, and the actual/target controls are empty. Bringing up the PlotlyTempGraph Settings dialog also "hangs" -- the page looks okay, but the Save button has a rotating "busy" symbol and the Close button does nothing.

I then uninstalled 0.1.3 with "uninstall and clean up data". That put me back to a functioning, default format Temperature tab.

I tried installing 0.1.3 again. Same as before, I had a non-functional Temperature tab with no graph and empty actual/target controls, and the settings dialog hangs.

Uninstalled 0.1.3 with "uninstall and clean up data", re-installed 0.1.4 from repository, set channel to RC and updated to 0.1.5rc. Also had to re-install my custom version of the SystemCmdMulti.py plugin, and customize settings. So I think I am now back where I was....

(The "close with comment" button was inadvertently hit while composing -- so I reopened. Sorry about that.)

ScottWell1 commented 1 year ago

I did find a "workaround". It's kind of a kludge, but I will mention it in case it prompts some idea of how to better handle it.

My external script for the custom sensor was returning 0 when the fan was off, and Plotly was having problems with the 0 (kept plotting the last non-zero value when it changed to zero). So... I changed the script to return 0.1 when the fan was off and changed the new hover_template format from ".1f" to ".0f".

So now the value is always positive (0.1 when fan is actually at 0), and Plotly consistently plots it. The line being at 0.1 is indistinguishable from 0, and the hover_template rounds the 0.1 to 0 on display. See the "Exhaust" sensor in the example below.

image

jneilliii commented 1 year ago

Can you share your single file plugin code? I did a test with the below code and 0 shows up fine for me. I did just notice that there is a bug in the hovertemplate code as it's not added to newly created lines and will be releasing another rc version shortly.

# coding=utf-8
from __future__ import absolute_import
import octoprint.plugin

class DebugZero(octoprint.plugin.StartupPlugin):
    def __init__(self):
        self.temp = 100

    def callback(self, comm, parsed_temps):
        if self.temp >= 100:
            self.temp = 0
        else:
            self.temp = self.temp + 10
        parsed_temps.update(test = (self.temp, None))
        return parsed_temps

__plugin_name__ = "Test Plotly Graph"
__plugin_pythoncompat__ = ">=2.7,<4"
__plugin_version__ = "0.1.0"
__plugin_implementation__ = DebugZero()
__plugin_hooks__ = {
    "octoprint.comm.protocol.temperatures.received": (__plugin_implementation__.callback, 1)

gives me this

image

ScottWell1 commented 1 year ago

The single-file plugin is from your github "examples" folder, the "SystemCmdMultiGraph.py" file. I simply changed the SYSTEM_CMDS to contain calls to my bash scripts (the same bash scripts previously used and working with TopTemp).

SYSTEM_CMDS = {
        'Enclosure': {
                'cmd': "PATH='/bin';bash /home/pi/.octoprint/scripts/get_enclosure_probe_temp",
                'precision': 1,
                'convertTo_celsius': False,
                'convertTo_fahrenheit': False,
        },
        'Exhaust': {
                 'cmd': "PATH='/bin';bash /home/pi/.octoprint/scripts/getFanPct",
                 'precision': 1,
                 'convertTo_celsius': False,
                 'convertTo_fahrenheit': False,
        }
}

The bash script getFanPct checks the status of a relay. If off, it returns 0 as the fan speed, otherwise it returns the pwm duty cycle.

#!/bin/bash
chan="pwm1"      #use chan="pwm0" for gpio18/pin12, or chan="pwm1" for gpio19/pin35
freq=40000  #constant for pwm frequency (Noctua)

gpio=23
stat=`gpio -g read $gpio`

if [ $stat = 0 ]; then
  echo 0
else
  duty_cycle=`cat /sys/class/pwm/pwmchip0/$chan/duty_cycle`
  let pct=$duty_cycle*100/$freq
  echo $pct
fi

It works fine (as it did with TopTemp), except when it returns 0. When the script returns 0, Plotly keeps plotting the previous value. I know the script is returning 0 from (a) Running it manually;, and (b) TopTemp is calling the same script and it properly shows (and plots) the 0 value.

If I simply change that "echo 0" to "echo 0.1", then when the relay is off the 0.1 value is shown in TopTemp, and Plotly plots it as 0.1 as well. If I change it back to "echo 0", TopTemp still displays it correctly but Plotly just keeps plotting the previous non-zero value when the fan speed changes from positive to zero.

jneilliii commented 1 year ago

can you change this line https://github.com/jneilliii/OctoPrint-PlotlyTempGraph/blob/6708787caefd87c0cb1f7e3597c398b9204c2733/examples/SystemCmdMultiGraph.py#L87 to

                                        self._logger.info(" {} : {}".format(sensor, current_temp))

and we can see how a 0 returned from bash script is handled. I didn't make that example so not fully sure if there are any quirks.

ScottWell1 commented 1 year ago

Your "DebugZero" example above proves PlotlyTempGraph itself handles the 0 correctly, and I am sure my bash scripts are returning 0 (as opposed to nulls or something). That seems to point to a problem in that SystemCmdMultiGraph.py example, somewhere between getting the raw data from bash and handing it over to PlotlyTempGraph. Unfortunately, my python experience fits in a thimble, so I don't see anything obvious in the code, but I'm thinking it must be tossing out 0 values somewhere.

It's late here now, but I will add the logger.info() call as requested in the morning -- hopefully that will provide a clue. THANKS for your help!

ScottWell1 commented 1 year ago

I couldn't stop looking at this....

Immediately after SystemCmdMultiGraph.py calls the bash script, it converts it to a float and stores it in current_temp. The next block, which is responsible for setting "self.last_temps[sensor]", starts with "if current_temp:".

Pardon my python ignorance here, but won't that IF evaluate as false when current_temp is 0? Should that line be something like "if current_temp is not None:" when 0 values are expected in current_temp?

jneilliii commented 1 year ago

Pardon my python ignorance here, but won't that IF evaluate as false when current_temp is 0? Should that line be something like "if current_temp is not None:" when 0 values are expected in current_temp?

Yeah, something like this was my suspicion and your is not None would be a good fix.

ScottWell1 commented 1 year ago

Okay, that IF statement in SystemCmdMultiGraph.py was the problem.

I changed this line: https://github.com/jneilliii/OctoPrint-PlotlyTempGraph/blob/6708787caefd87c0cb1f7e3597c398b9204c2733/examples/SystemCmdMultiGraph.py#L80

to if current_temp is not None:

That solves the issue, 0 values now get delivered to PlotlyTempGraph.

Thanks very much for your help!

jneilliii commented 1 year ago

Cool, I'll make sure to update the example.