How to make Domoticz read I2C data directly from the GPIO?

Topics (not sure which fora)
when not sure where to post, post here and mods will move it to right forum.

Moderators: leecollings, remb0

Post Reply
User avatar
pgielen
Posts: 91
Joined: Monday 18 February 2019 14:44
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Boxmeer
Contact:

How to make Domoticz read I2C data directly from the GPIO?

Post by pgielen »

I am looking for a way to read I2C data in Domoticz from the Raspberry Pi 4B that Domoticz is running on. I have recently installed a X728 power management board on this RPi, in order to make my Domoticz system less vulnerable to power failure.

The X728 uses two GPIO pins for a I2C interface to send the voltage and battery levels to the RPi and I want to read out these values directly into Domoticz, but can't find out how. I tried to use the I2C sensors hardware type in Domoticz, but this seems to be meant for other hardware.

Is there another way? There should be. The X728 board does come with a Python example for sending voltage and battery levels to the console, but I could not import that script (which runs fine when executed from the CLI) into the Domoticz script system because I immediately get an error in line 3, where it says: import smbus. This lib is installed on my system. Python finds it, but Domoticz doesn't.

And then there is the question about how to get the data into Domoticz variables. The Wiki is not clear on how to do this. Running the script outside of Domoticz and then sending a http request with the data over the internet could work, but really doesn't sound like an elegant solution for two devices that are physically connected to eachother. So what else could I try? I am not asking for a specific solution in Python, just some easy way to get the job done.

BTW the X728 example script is here:

Code: Select all

#!/usr/bin/env python
import struct
import smbus
import sys
import time

def readVoltage(bus):
     address = 0x36
     read = bus.read_word_data(address, 2)
     swapped = struct.unpack("<H", struct.pack(">H", read))[0]
     voltage = swapped * 1.25 /1000/16
     return voltage

def readCapacity(bus):
     address = 0x36
     read = bus.read_word_data(address, 4)
     swapped = struct.unpack("<H", struct.pack(">H", read))[0]
     capacity = swapped/256
     return capacity

bus = smbus.SMBus(1) # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1)

while True:
 print "******************"
 print "Voltage:%5.2fV" % readVoltage(bus)
 print "Battery:%5i%%" % readCapacity(bus)
 if readCapacity(bus) == 100:
         print "Battery FULL"
 if readCapacity(bus) < 20:
         print "Battery LOW"
 print "******************"
 time.sleep(2)
 
https://robothuis.nl, RPi4B, RFXCOM XL, Aeotec Z-Stick, ESP Easy, Weatherstation, several switches and sensors, Ikea Trädfri, Philips Hue, Foscam, Reolink, Lyric T6, Ring
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: How to make Domoticz read I2C data directly from the GPIO?

Post by waaren »

pgielen wrote: Tuesday 28 July 2020 15:18 And then there is the question about how to get the data into Domoticz variables. Running the script outside of Domoticz and then sending a http request with the data over the internet could work, but really doesn't sound like an elegant solution
This is a perfectly good solution. The domoticz API is designed for this and your http request will not leave the system. If you enter 127.0.0.1 or the IP address the system received from your router, your network interface will recognize that. No intranet or internet will be used.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
User avatar
pgielen
Posts: 91
Joined: Monday 18 February 2019 14:44
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Boxmeer
Contact:

Re: How to make Domoticz read I2C data directly from the GPIO?

Post by pgielen »

Okay then, this works as an external Python script, but still not from within the Domoticz script system:

Code: Select all

#!/usr/bin/env python
import struct
import smbus
import sys
import time
import requests


def readVoltage(bus):

     address = 0x36
     read = bus.read_word_data(address, 2)
     swapped = struct.unpack("<H", struct.pack(">H", read))[0]
     voltage = swapped * 1.25 /1000/16
     return voltage


def readCapacity(bus):

     address = 0x36
     read = bus.read_word_data(address, 4)
     swapped = struct.unpack("<H", struct.pack(">H", read))[0]
     capacity = swapped/256
     if (capacity > 100): # Added because the capacity sometimes reaches > 100
          capacity = 100
     return capacity

bus = smbus.SMBus(1) # (port I2C1)

voltage = "%.2f" % readVoltage(bus)
battery = "%i" % str(readCapacity(bus))
url = "http://127.0.0.1:8088/json.htm?type=command&param=udevice&idx=561&nvalue=0&svalue=" + voltage
r = requests.get(url)
#print(r) # for debugging: result should  be 200 = OK

url = "http://127.0.0.1:8088/json.htm?type=command&param=udevice&idx=562&nvalue=0&svalue=" + battery
r = requests.get(url)
#print(r) 
(idx 561 is a virtual device of the type Voltage, idx 562 is a virtual device of the type Percentage)

I have it working when triggered as an external script through crontab, but if i try to run this code from within the Domoticz script system, I still get:

Code: Select all

2020-07-29 12:04:40.152 Error: EventSystem: ModuleNotFoundError: No module named 'smbus' 
Could this error be related to a PATH variable or something like that, or is the Python version built in Domoticz just a bit more limited than the full version?
https://robothuis.nl, RPi4B, RFXCOM XL, Aeotec Z-Stick, ESP Easy, Weatherstation, several switches and sensors, Ikea Trädfri, Philips Hue, Foscam, Reolink, Lyric T6, Ring
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest