Page 1 of 2
GPIO Interrupt for water meter
Posted: Monday 09 February 2015 19:22
by bram2202
Hello,
I'm trying to hook up my analog water meter to my Domoticz.
So i bought a metal Detector:
http://www.dx.com/p/k1208065-metal-dete ... ack-151198
(using WiringPi)
-It now Pulls pin 40 to 3.3v
-set the pin internal to pull down
-set the interrupt to 'rising'
-Created a RFXmeter/counter (Idx15)
-Create a user variable
when i use json to send the total number it works:
/json.htm?type=command¶m=udevice&15=IDX&svalue=520
but the next thing is to create a script (python?) who can handle the GPIO interrupt, add a number to a saved var and send the json.
but im stuck.
how can i create a script that start on boot, and triggers on interrupt. and uses a var that not losses its value on a reboot??
Could someone please help me?

Re: GPIO Interrupt for water meter
Posted: Monday 16 February 2015 15:18
by bram2202
Fixed it
Code: Select all
#!/usr/bin/env python
# PIN: 23 == GPIO4 (pin 16)
#imports
import time
import RPi.GPIO as GPIO
import json
import urllib2
import base64
#vars
GET_URL = 'http://192.168.1.205:8080/json.htm?type=command¶m=getuservariable&idx=1'
SET_URL = 'http://192.168.1.205:8080/json.htm?type=command¶m=udevice&idx=15&svalue='
SET_VAR_URL = 'http://192.168.1.205:8080/json.htm?type=command¶m=updateuservariable&idx=1&vname=Water&vtype=0&vvalue='
WATER_VALUE = 0
base64string = base64.encodestring('%s:%s' % ('username', 'password')).replace('\n', '')
# handle the trigger event
def Trigger (pin):
if GPIO.input(23):
global WATER_VALUE
WATER_VALUE += 1
# print WATER_VALUE
POST_URL = SET_URL + str(WATER_VALUE)
global base64string
requestPost = urllib2.Request(POST_URL)
requestPost.add_header("Authorization", "Basic %s " % base64string)
resultPost = json.load(urllib2.urlopen(requestPost))
# print resultPost
POST_VAR = SET_VAR_URL + str(WATER_VALUE)
requestVar = urllib2.Request(POST_VAR)
requestVar.add_header("Authorization", "Basic %s " % base64string)
resultVar = json.load(urllib2.urlopen(requestVar))
# print resultVar
# main function
def main():
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(23, GPIO.RISING, callback=Trigger, bouncetime=500)
request = urllib2.Request(GET_URL)
global base64string
request.add_header("Authorization", "Basic %s " % base64string)
result = json.load(urllib2.urlopen(request))
global WATER_VALUE
WATER_VALUE = int( result['result'][0]['Value'])
print WATER_VALUE
while True:
time.sleep(1)
# GPIO.cleanup()
if __name__=="__main__":
main()
I used Python instead of C, because its easter to use web request with 'urllib2'.
And i use a var created in the Domoticz, easier to setup and readout after a power loss.
rc.local cals a script that launches this python on launch.
and set water divider to 1000 instead of 100, because the script is triggered every 1 liter.
if you have any questions or comments, please feel free to post them.
Re: GPIO Interrupt for water meter
Posted: Monday 16 February 2015 19:12
by sincze

nice. Hopefully no fake interrupts that will screw your water usage.
bram2202 wrote:Fixed it
Code: Select all
#!/usr/bin/env python
# PIN: 23 == GPIO4 (pin 16)
#imports
import time
import RPi.GPIO as GPIO
import json
import urllib2
import base64
#vars
GET_URL = 'http://192.168.1.205:8080/json.htm?type=command¶m=getuservariable&idx=1'
SET_URL = 'http://192.168.1.205:8080/json.htm?type=command¶m=udevice&idx=15&svalue='
SET_VAR_URL = 'http://192.168.1.205:8080/json.htm?type=command¶m=updateuservariable&idx=1&vname=Water&vtype=0&vvalue='
WATER_VALUE = 0
base64string = base64.encodestring('%s:%s' % ('username', 'password')).replace('\n', '')
# handle the trigger event
def Trigger (pin):
if GPIO.input(23):
global WATER_VALUE
WATER_VALUE += 1
# print WATER_VALUE
POST_URL = SET_URL + str(WATER_VALUE)
global base64string
requestPost = urllib2.Request(POST_URL)
requestPost.add_header("Authorization", "Basic %s " % base64string)
resultPost = json.load(urllib2.urlopen(requestPost))
# print resultPost
POST_VAR = SET_VAR_URL + str(WATER_VALUE)
requestVar = urllib2.Request(POST_VAR)
requestVar.add_header("Authorization", "Basic %s " % base64string)
resultVar = json.load(urllib2.urlopen(requestVar))
# print resultVar
# main function
def main():
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(23, GPIO.RISING, callback=Trigger, bouncetime=500)
request = urllib2.Request(GET_URL)
global base64string
request.add_header("Authorization", "Basic %s " % base64string)
result = json.load(urllib2.urlopen(request))
global WATER_VALUE
WATER_VALUE = int( result['result'][0]['Value'])
print WATER_VALUE
while True:
time.sleep(1)
# GPIO.cleanup()
if __name__=="__main__":
main()
I used Python instead of C, because its easter to use web request with 'urllib2'.
And i use a var created in the Domoticz, easier to setup and readout after a power loss.
rc.local cals a script that launches this python on launch.
and set water divider to 1000 instead of 100, because the script is triggered every 1 liter.
if you have any questions or comments, please feel free to post them.
Re: GPIO Interrupt for water meter
Posted: Monday 16 February 2015 19:55
by ThinkPad
Instead of 192.x.x.x IP you can use 127.0.0.1 to make the script futureproof (if you ever change IP of your Pi).
Wish i could read my watermeter, but is some old thing with no shiny reflecting part or magnet unfortunately....
http://gathering.tweakers.net/forum/lis ... es/1596066
Re: GPIO Interrupt for water meter
Posted: Monday 22 June 2015 10:53
by Hesmink
Hi,
How did you connect this sensor to your RPI?
Re: GPIO Interrupt for water meter
Posted: Saturday 25 July 2015 18:29
by Hesmink
So, I almost got it working, up to the point that if I hold something metal to the sensor, the counter in Domoticz increases by 1.
I used the standard GPIO pins to connect the sensor, I connected brown to +5v, blue to ground and black to GPIO4.
Between black and blue I added a 10K resistor, as stated here:
http://forum.arduino.cc/index.php?topic=210921.0
It detects metal, but it seems to weak to detect the revolving disk in the water meter.
Is there any way to increase detection? Does it need a higher voltage than 5V? Other resistor maybe?
Or is something else wrong?
Any help is appreciated.
Re: GPIO Interrupt for water meter
Posted: Tuesday 28 July 2015 11:35
by Hesmink
Hesmink wrote:So, I almost got it working, up to the point that if I hold something metal to the sensor, the counter in Domoticz increases by 1.
I used the standard GPIO pins to connect the sensor, I connected brown to +5v, blue to ground and black to GPIO4.
Between black and blue I added a 10K resistor, as stated here:
http://forum.arduino.cc/index.php?topic=210921.0
It detects metal, but it seems to weak to detect the revolving disk in the water meter.
Is there any way to increase detection? Does it need a higher voltage than 5V? Other resistor maybe?
Or is something else wrong?
Any help is appreciated.
No ideas?
I'm no electrical genius, so any help is appreciated.
Re: GPIO Interrupt for water meter
Posted: Tuesday 28 July 2015 12:06
by ThinkPad
Maybe you can exchange the resistor for a different value? Or a potmeter so you can adjust it?
But i'm not sure how the sensor works, you don't want to blow up the sensor

Re: GPIO Interrupt for water meter
Posted: Wednesday 29 July 2015 20:44
by Hesmink
ThinkPad wrote:Maybe you can exchange the resistor for a different value? Or a potmeter so you can adjust it?
But i'm not sure how the sensor works, you don't want to blow up the sensor

Well, it turns out either the detector is too weak, or the shiny part on the dial is not metal.
I first hooked the sensor up to 12v, and later to 15v, but not detection happens (just looking at the detection led on the sensor).
Any other metal object I try it on detects fine.
I have an Itron flodis.
Re: GPIO Interrupt for water meter
Posted: Tuesday 12 January 2016 21:58
by multinet
Hello
i've modified the script with my IP and my GPIO
but when i start it i go this error :
Code: Select all
pi@raspberrypi ~/WORK $ sudo python ./counter.py
Traceback (most recent call last):
File "./counter.py", line 65, in <module>
main()
File "./counter.py", line 56, in main
WATER_VALUE = int( result['result'][0]['Value'])
KeyError: 'result'
do you have any idea why ?
Thank you!
Multinet
Re: GPIO Interrupt for water meter
Posted: Monday 14 March 2016 22:09
by JelleB
Bram2202,
would you be able to share/give some more guidance on how to modify the script (other than ip adress, port, pin nr and GPIO nr)?
I guess the script will be stored in /scripts and made executable. I did all this and get the same errors as above user.
Also, how did you specify this counter as RFX? I have connected it as hardware: PI GPIO pin.
Were are the # of pulses stored?
Thanks in advance.
Jelle
Re: GPIO Interrupt for water meter
Posted: Thursday 17 March 2016 11:39
by RidingTheFlow
Here is script I made based on above idea. This script is very resilient and should never miss pulses as long as it running (e.g. even if Domoticz stalls/stops it will keep accumulating counts and will send update to Domoticz when it can). Also it minimizes amount of code running inside interrupt handler, avoiding swamping Domoticz with update requests, high CPU usage or even missed updates if many pulses happen quickly.
You can adjust delay inside main loop to whatever *maximum* frequency you want Domoticz to be updated (script won't even bother trying to update if counter does not change). It will never miss pulses so can be whatever you want, but 30 secs is reasonable considering 1 minute is generally lowest precision you can get from Domoticz reports anyway.
This script requires that you make "Virtual Incremental Counter" in "Dummy" device on Domoticz and set their IDs as GAS_IDX & ELEC_IDX inside script
Set GAS_GPIO and ELEC_GPIO to your input GPIOs
Code: Select all
#!/usr/bin/env python
#imports
import time
import RPi.GPIO as GPIO
import json
import urllib2
import threading
#vars
GET_URL = 'http://localhost:8080/json.htm?type=devices&rid=%d'
SET_URL = 'http://localhost:8080/json.htm?type=command¶m=udevice&idx=%d&svalue=%d'
GAS_DELTA = 0
GAS_IDX = 3
GAS_GPIO = 26
GAS_COUNTER_LOCK = threading.Lock()
ELEC_DELTA = 0
ELEC_IDX = 4
ELEC_GPIO = 16
ELEC_COUNTER_LOCK = threading.Lock()
def gpio_intr(pin):
if pin == GAS_GPIO:
global GAS_DELTA
with GAS_COUNTER_LOCK:
GAS_DELTA += 1
print 'Gas counter tick: %d' % GAS_DELTA
if pin == ELEC_GPIO:
global ELEC_DELTA
with ELEC_COUNTER_LOCK:
ELEC_DELTA += 1
print 'Electricity counter tick: %d' % ELEC_DELTA
def main():
global GAS_DELTA
global ELEC_DELTA
GPIO.setmode(GPIO.BCM)
GPIO.setup(GAS_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(GAS_GPIO, GPIO.RISING, callback=gpio_intr, bouncetime=100)
GPIO.setup(ELEC_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(ELEC_GPIO, GPIO.RISING, callback=gpio_intr, bouncetime=100)
while True:
time.sleep(5)
GAS_DELTA_POST = GAS_DELTA
if GAS_DELTA_POST != 0:
try:
res = json.load(urllib2.urlopen(SET_URL % (GAS_IDX, GAS_DELTA_POST)))
if res['status'] != 'OK':
raise Exception('Domoticz json error')
with GAS_COUNTER_LOCK:
GAS_DELTA -= GAS_DELTA_POST
except Exception as e:
print e
ELEC_DELTA_POST = ELEC_DELTA
if ELEC_DELTA_POST != 0:
try:
res = json.load(urllib2.urlopen(SET_URL % (ELEC_IDX, ELEC_DELTA_POST)))
if res['status'] != 'OK':
raise Exception('Domoticz json error')
with ELEC_COUNTER_LOCK:
ELEC_DELTA -= ELEC_DELTA_POST
except Exception as e:
print e
print 'Gas delta %d; Elec delta %d' % (GAS_DELTA_POST, ELEC_DELTA_POST)
if __name__=="__main__":
main()
To set your "actual" meter values, issue "fake update" to meter via JSON, or run script with initial xxx_DELTA set to appropriate values -
but only do this *once*, normally script must start with deltas set to zero, or it will increase meter every time it restarts.
Startup of script & output logging is up to you.
E.g. you can start it up on boot with cron & disable unnecessary print statements (or configure Python logging to log to file).
Update: tabs fixed.
Re: GPIO Interrupt for water meter
Posted: Sunday 20 March 2016 14:59
by JelleB
Ridingthe flow,
this works with me. However, when opening the water tap, I see the counter increments but also get some 'Domoticz Json error' warnings. What could this mean?
Also, how do I get the counter values as nicely configured variable in the Utilities tab of the domoticz web interface?
Re: GPIO Interrupt for water meter
Posted: Sunday 20 March 2016 15:02
by RidingTheFlow
Did you follow the bold text instructions to create a Dummy hardware and virtual increment counters?
Script will not create an actual device for you, you need to create virtual device manually (then you will see it in UI), and put device ID in the script so script will update it.
P.S. Maybe you made device of wrong type. You need to make "Increment Counter", only this one will work with this script. After you created increment counter you can change its subtype to "water".
Re: GPIO Interrupt for water meter
Posted: Sunday 20 March 2016 15:15
by JelleB
Yes I did and replaced 'GAS' with 'WATER'.
Indeed the Virtual increment counter shows up as watermeter and data 0 kWh. Should I select another dummy, to get water in liters or can i edit the properties of the dummy?
IDX should be the IDX of the dummy device (not the hardware IDX)
Re: GPIO Interrupt for water meter
Posted: Sunday 20 March 2016 15:17
by RidingTheFlow
Click "edit" button on device, and set "type" to "water". This should change device icon to water droplet and it should show m^3.
Device "Idx" is from "devices" table.
Re: GPIO Interrupt for water meter
Posted: Sunday 20 March 2016 22:03
by JelleB
Got it.
When I start the script manually it prints the delta and the ticks and increments the liters in domoticz.
I added the automatic start of the scriot to crontab:
@reboot python /home/pi/domoticz/scripts/watermeter.py &
However, upon reboot, the counter is not incremented and the meter in the dashboard shows 'last seen ...10 min ago or something. Also the total liters is not shown.
What can be wrong?
Re: GPIO Interrupt for water meter
Posted: Monday 21 March 2016 10:05
by RidingTheFlow
You need root to run script and you don't need & for crontab.
Try
Code: Select all
@reboot sudo python /home/pi/domoticz/scripts/watermeter.py
Check after reboot if script is running with
Re: GPIO Interrupt for water meter
Posted: Monday 21 March 2016 12:17
by JelleB
Thanks, removed the & from crontab and checked the scripts is runnng.
The sensor on the watermeter nicely blinks every liter, however Domoticz reports I have used 20 m3 since yesterday. This does not make sense.
How can I monitor what the script sends back to domoticz (run print statements in the terminal?) and how can I reset the incremetal counter to 0 ?
Re: GPIO Interrupt for water meter
Posted: Monday 21 March 2016 14:49
by RidingTheFlow
The data is being posted to domoticz near line json.load(urllib2.urlopen(SET_URL ....
You can put a print there to see what it post and when.
You can't really "reset"a counter, many things go crazy if counter tries to go backwards. You will need to delete a counter and create a new one.