Hi, If its of any use and you don’t mind using node red I created a function for detecting the rate of rise of temperature but you could adapt it for your use. The function just really compares two values it receives in succession and calculates the difference. So for the actual rate of rise you would need to send the temp/humidity values at an interval of 1 min or more.
Node Red Flow
[{"id":"e6994f2d.a8f94","type":"function","z":"4b74def4.25059","name":"compare","func":"// See Setup TAB for where the variables are initialised.\n// Function to compare 2 values to send a payload based on either\n// rate of rise trigger or Max Temperature reached\n\n\n\nvar previoustemp = context.get('previoustemp'); //previous temperature value\nvar currenttemp = context.get('currenttemp'); // current temperature value\nvar payloadtemp = msg.payload; // current temperature value\n\n// Change the RoR value for the Rate of Rise trigger \nvar RoR = 7.5;\n// Change the MAX Temperature Value \nvar maxtemp = 60;\n\n\ncontext.set('currenttemp',payloadtemp); //set the current temperature to temp2 variable\ncurrenttemp=context.get('currenttemp');\n\n//Temperature difference between 2 values\ntempdif=currenttemp-previoustemp; \n\n// set the message payload based on conditions\nif ((previoustemp == -300) && (maxtemp > payloadtemp)) {msg.payload=\"Previous temp is null can't give rate of rise yet until i receive another value\"}\nelse if (maxtemp < payloadtemp) {msg.payload={\"FireDetected\":\"true\", \"MaxTemp\":payloadtemp}}\nelse if (tempdif > RoR) {msg.payload={\"FireDetected\":\"true\", \"RateofRise\":tempdif };}\nelse if (previoustemp !== -300) {msg.payload={\"FireDetected\":\"false\", \"RateofRise\":tempdif};}\n\n// set previous temperature to the value of current temperature\ncontext.set('previoustemp',currenttemp);\n\n// Return the new message\nreturn msg;\n\n\n\n\n\n\n\n\n// if (temp3>6.7) {\n// msg.payload= \"on \" + count + temp1 +temp2;\n// return msg.payload;\n//} else {\n// return null\n//}\n","outputs":1,"noerr":0,"initialize":"//Initialise the variables \nvar previoustemp = context.get('previoustemp') || -300; //previous temperature value\nvar currenttemp = context.get('currenttemp') || -300; // current temperature value\nvar tempdif =null;\ncontext.set('previoustemp',-300);","finalize":"","x":300,"y":640,"wires":[["f2b59f04.059708"]]},{"id":"d3f359ba.7105e8","type":"inject","z":"4b74def4.25059","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"4","payloadType":"num","x":130,"y":620,"wires":[["e6994f2d.a8f94"]]},{"id":"7f6a7349.ff7714","type":"inject","z":"4b74def4.25059","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":130,"y":660,"wires":[["e6994f2d.a8f94"]]},{"id":"ed8d44b7.85f87","type":"inject","z":"4b74def4.25059","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"20","payloadType":"num","x":130,"y":700,"wires":[["e6994f2d.a8f94"]]},{"id":"f2b59f04.059708","type":"debug","z":"4b74def4.25059","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":480,"y":640,"wires":[]},{"id":"e13159fc.392a88","type":"inject","z":"4b74def4.25059","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":130,"y":580,"wires":[["e6994f2d.a8f94"]]},{"id":"5cc2a0c5.2b13","type":"inject","z":"4b74def4.25059","name":"Max Temp 61","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"61","payloadType":"num","x":150,"y":740,"wires":[["e6994f2d.a8f94"]]}]