Now for an example i will take SENSOR-A, label it battery, if that temp, rises over 30deg C, it will run the relay on pin lets say IN1 , SENSOR-B , label Inverter gets over 40 deg C turn on IN2, ect C,D E.F ect
As you can see, original script running like a dream, want to do a seperate script, to do the control, what i tried to do was, cut and paste bits, to create a new script “relay-fan.py”
Why must it be a separate script? IMO that is complicating things. I would favour just adding the control part after each sensor is read in the script we have.
#!/usr/bin/python3
import glob
import time
import paho.mqtt.publish as publish
import RPi.GPIO as gpio
Broker = '127.0.0.1'
auth = {
'username': 'emonpi',
'password': 'emonpimqtt2016',
}
Sensors = {{'name':'SENSOR_A','id':'28-800000abc123','pin':1,'on':20,'off':15},
{'name':'SENSOR_B','id':'28-800000def456','pin':2,'on':20,'off':15},
{'name':'SENSOR_C','id':'28-800000abc456','pin':3,'on':20,'off':15}}
def read_temp(sensorid):
valid = False
temp = 0
device_file = '/sys/bus/w1/devices/' + sensorid + '/w1_slave'
with open(device_file, 'r') as f:
for line in f:
if line.strip()[-3:] == 'YES':
valid = True
temp_pos = line.find(' t=')
if temp_pos != -1:
temp = float(line[temp_pos + 3:]) / 1000.0
if valid:
return temp
else:
return None
gpio.setmode(gpio.BOARD)
for sensor in Sensors:
gpio.setup(sensor['pin'], gpio.OUT)
gpio.output(sensor['pin'], gpio.HIGH)
while True:
for sensor in Sensors:
temp = read_temp(sensor['id'])
if temp is not None:
pub_topic = 'emon/Temperatures/' + sensor['name'] + '/values'
publish.single(pub_topic, str(temp),
hostname=Broker, port=1883,
auth=auth,)
if temp >= sensor['on']:
gpio.output(sensor['pin'], gpio.LOW)
elif temp <= sensor['off']:
gpio.output(sensor['pin'], gpio.HIGH)
time.sleep(6)
The usual warning applies as I’ve just knocked this out without testing.
You need to give some thought to what should happen if a sensor is uncontactable or errors, ie if temp IS None (for a prolonged time?), what should the fan be doing then?
With this arrangement it would also be very easy to add a line or 2 to publish the current (expected) relay state, ie what the pin output is, this would assume the relay and fan are connected and working to the pin status.
Note the bogus pin numbers I have used in the revised “Sensors” layout, the “on” and “off” are the setpoints and can be ints or floats, be sure not to quote those values (making them strings). You also need to check if you are using BOARD or BCM GPIO pin numbering and set the gpio.setmode(gpio.BOARD) line to suit.
I’m off out for most of the day now so won’t be able to assist much further today I’m afraid.
[edit - Oh, and I have assumed the pins will be high at rest (off) and held active low (on) for the relays, if that’s wrong, change both HIGH’s to LOW’s and the one LOW to HIGH.
1st Thank you so much for the time you spent , with helping me, i really do appreciate allot.
You 100% right does make more sense.I did not want to mess with the original script that you wrote.
I would think for safety that the fan should turn on and run, better cold than too hot ?
That is a fantastic idea the state of the fan as a ON or OFF condition. ( SENSOR A- FAN ON/OFF) it takes out the guess work as to the state of the fan.
As per script ill use (gpio. board ) the physical pin numbering of the board if i understand that correctly.
I take it the 20 and 15 ints or floats that’s where i have no idea.
I take it if i look at the code, 20 deg will turn on, and 15 deg turn off, but i take it, i cannot use it like that 20 and 15 needs to be changed (total lost with that, searched hours on google to try and find info that made sense to me, sorry not a programing person but i really want to learn.
Thank you again for all the help, much appreciated
For our purpose here (although the datatype can be int or float) i was simply saying that the on and off values can be whole numbers or decimal, they are the setpoints in Centigrade (sorry I omitted that small detail) so you can set the fan to come on at 40°C and off at 33.333333°C should you choose, the values I put in there (20 and 15) were just random values, obviously the off needs to be lower than the on setpoint so that the fan comes on when hot and off again once cooled.
Below I have added publishing the fan status, unfortunately emoncms only understands numeric data so it has to be “1” and “0” for on and off. There are 2 options, if you look at the publish lines there are 2 at each of 3 points, one of which (at each point) is commented out with a “#”. As it stands it will publish in a way that gives you 2 nodes, one “Temperatures” and the other “Fans” as this is close to what you have, if you switch over to the commented versions (by removing the “#” and adding a “#” to the beginning of the previous line) it will create as many nodes as you have sensor and fan pairs, each node will have 2 values, status and temperature, this might be preferable to you maybe? Once you decide you can just delete the 3 unused lines.
#!/usr/bin/python3
import glob
import time
import paho.mqtt.publish as publish
import RPi.GPIO as gpio
Broker = '127.0.0.1'
auth = {
'username': 'emonpi',
'password': 'emonpimqtt2016',
}
Sensors = {{'name':'SENSOR_A','id':'28-800000abc123','pin':1,'on':20,'off':15},
{'name':'SENSOR_B','id':'28-800000def456','pin':2,'on':20,'off':15},
{'name':'SENSOR_C','id':'28-800000abc456','pin':3,'on':20,'off':15}}
def read_temp(sensorid):
valid = False
temp = 0
device_file = '/sys/bus/w1/devices/' + sensorid + '/w1_slave'
with open(device_file, 'r') as f:
for line in f:
if line.strip()[-3:] == 'YES':
valid = True
temp_pos = line.find(' t=')
if temp_pos != -1:
temp = float(line[temp_pos + 3:]) / 1000.0
if valid:
return temp
else:
return None
def publish_data(topic, value):
publish.single(topic, str(value),
hostname=Broker, port=1883,
auth=auth,)
return
gpio.setmode(gpio.BOARD)
for sensor in Sensors:
gpio.setup(sensor['pin'], gpio.OUT)
gpio.output(sensor['pin'], gpio.HIGH)
while True:
for sensor in Sensors:
temp = read_temp(sensor['id'])
if temp is not None:
publish_data('emon/Temperatures/' + sensor['name'] + '/values', temp)
#publish_data('emon/' + sensor['name'] + 'Temperature/values', temp)
if temp >= sensor['on']:
gpio.output(sensor['pin'], gpio.LOW)
publish_data('emon/Fans/' + sensor['name'] + '/values', 1)
#publish_data('emon/' + sensor['name'] + '/Status/values', 1)
elif temp <= sensor['off']:
gpio.output(sensor['pin'], gpio.HIGH)
publish_data('emon/Fans/' + sensor['name'] + '/values', 0)
#publish_data('emon/' + sensor['name'] + '/Status/values', 0)
time.sleep(6)
@tonertiffi did you try and google the error message? so Google TypeError: unhashable type: 'dict' and see what you might find - a number of results do appear (I don’t know the answer BTW).
My bad, in my head I had changed the Sensors format to a list of dicts but failed to make that edit. Change the 2 outer curly braces to square bracket like so
I will try and keep an eye on the forum in case you have further issues, but I have quite a bit on this weekend so I do not know if or when I might be about yet.
You are truly brilliant @pb66 . Attached screen shots, from 1st to last, the relay does activate and deactivate. Never had to change anything in the code except for the [ ].
Just that i understand readings go red, take it, it cannot read the state of the pin?
When state turns back to 0 it carries on reading it no problem.
Thank you very much.
That makes sense, I had just added the publish line to the change of pin status code so it only publishes when the state changes, that is how I would expect a “status” to work on MQTT, but you are right, emoncms expects a constantly updating value I guess, for graphs etc to view better.
it’s an easy fix, change the existing control code like so
The status variables also needs defining before entering the main loop, just in case a temp reading is None and it tries to publish a status before it gets a valid read. Add sensor['status'] = 0 to the gpio setup code immediately before entering the main loop, eg
for sensor in Sensors:
gpio.setup(sensor['pin'], gpio.OUT)
gpio.output(sensor['pin'], gpio.HIGH)
sensor['status'] = 0
while True:
That’s most likely a copy and paste error. Python is very fussy about indentation, looking at the script there are 4 levels of indentation (plus no indentation). the if temp >= sensor['on']: line is on the 3rd level of indentation which means it probably must have 3 tabs or 12 spaces depending on what style you are using.
Beware of stray white space and or line endings altering things from what you see to what is seen by Python.
If you cannot resolve the problem you need to post the code you have leading up to and after the point it says is at fault as the required indention is defined by the code around it.
File "mqtt-temp", line 55
publish_data('emon/Fans/' + sensor['name'] + '/values', sensor['status'])
^
IndentationError: unindent does not match any outer indentation level
pi@emonpi:/usr/local/bin $