dragelec - monitoring the home


[2018-08-28 Tue 11:45] this was totally re-written during a 2hr flight; finally i achieved something useful on a plane.

What is dragelec?

Well it was a project initially started to alert me when there was a light or temperature issue with my bearded dragons enclosure and play a Polish radio station, it relied on;

 - one of the first raspberry pi's
 - a DS18B20 wired temperature sensor
 - an LDR
 - MPD - the commandline music player
 - some python code for monitoring and emailing

Then when someone i know started to take 45-90min showers on a daily basis (strangely something i objected to) i decided to re-write it to monitor electricity so that i could confront said individual with evidence and when that didn't work it was again expanded to automatically shut off the internet if the usage was >5.5kW for x minutes. It is/was quite surprising how quickly i earned the nickname The spy Stalin but also how the shower usage dropped dramatically once they'd figured out the correlation between long showers and no internet :-)

Over the years it has morphed and altered in part as a process of learning and in part due to expanding the things monitored and using different methods of data storage (csv,rrd)

So what is dragelec today [2018-08-28 Tue]? It is still based on the same principle but now runs on the same pi as piHole and only monitors temperatures which are logged into an SQLite db.

There is still work todo such as adding a query function to the site and graphing data plus as i learn improvements will be made and code added/altered and perhaps the whole thing will be re-written.

The program consists of the following;

dragelec.py - the main program
 - raspitemp.py - read the pi temp
 - decodesensors.py - decode temperature sensors &  assign to dictionary

rasPitemp - reading the Pi's temperature

Simple module to read the temperature reported by the python os module

#!/usr/bin/env python
def PiTemp(RTemp):
    import os
    # Return CPU temperature as a character string

    def getCPUtemperature():
        res = os.popen('vcgencmd measure_temp').readline()
        return(res.replace("temp=", "").replace("'C\n", ""))

    temp1 = int(float(getCPUtemperature()))

    return (temp1)

currently i do almost nothing with this, it is only displayed on the dashboard … i may consider adding an email alert for if the pi temp exceeds a yet to be decided limit but as it was originally done for my own learning it is left in.

decodesensors - receiving and using the values from wireless sensors

The wireless sensors used are unfortunately no longer available, the company (ciseco) simply vanished from existence along with all the documentation/firmware which is a shame as the wireless sensors were not expensive and have proven very reliable.

/img/dragelec/xrf-300x300.jpg

They use a protocol called LLAP (Lightweight Local Automation Protocol) essentially each device is programmed with the appropriate firmware and set to broadcast data on an interval. The transmitted data is a fixed length ASCII string which may look like aACTMPA18.78 and this is the user set device identifier (AC) and the data being sent (TMP18.78)

My main program polls the serial port for incoming data

    while True:
        n = ser.inWaiting()
        if n != 0:
            llapMsg = ser.read(n)

and if a message exists it passes the content to the decodesensor module;

sensordict['msg']=llapMsg
sensordict = decodesensor.decdict(sensordict)
def decdict(incoming):
    # sample: aAETMPA12.45
    if incoming.get('msg') != '':
        # get sensor id from llapmsg
        val = id = incoming.get("msg")
        id = id[1:3]
        # get value from llapmsg
        val = val[7:12]
        # assign value to correct sensor in dictionary
        incoming[id] = val

    return(incoming)

The above is a much shorter (perhaps improved) version of the original decode routine each value is now stored along with its identifier in a dictionary,

so from the recieved message we strip out the 2 letter identifier using a simple string handling function

id = id[1:3]

for me this could be AC,AE then we strip out the 4 digit value;

val = val[7:12]

and finally this is assigned to the correct id in the dictionary before the function returns

incoming[id] = val

Value storage - SQLite

All values are now stored in an SQLite database which means eventually i can display periodic data on the dashboard. Figuring out how to do this took me a little whilst but several examples can be found here: extracting sqlite . The data is stored right after the decode sensor function returns values;

c.execute("INSERT INTO {tn}(EXTERNAL,FRONTROOM,BEDROOM,KITCHEN) VALUES(?,?,?,?)".format(tn='home_mon'), (sensordict.get('AC'), sensordict.get('AB'), sensordict.get('AE'), sensordict.get('AD')))
conn.commit()
conn.close()

The database is created when the program is first run;

sqlite_file = Path('home_mon_db.sqlite'))
if my_file.is_file():
    # file exists
else:
    tn = 'home_mon'
    # Connecting to the database file
    conn = sqlite3.connect(sqlite_file)
    c = conn.cursor()
    # create table
    c.execute('CREATE TABLE {tn} ({nf} {ft} PRIMARY KEY AUTOINCREMENT)'.format(tn='home_mon', nf='IDX', ft='INTEGER') )
    c.execute("ALTER TABLE {tn} ADD COLUMN '{cn}' {ct}".format(tn='home_mon', cn="EXTERNAL", ct='REAL'))
    c.execute("ALTER TABLE {tn} ADD COLUMN '{cn}' {ct}".format(tn='home_mon', cn="FRONTROOM", ct='REAL'))
    c.execute("ALTER TABLE {tn} ADD COLUMN '{cn}' {ct}".format(tn='home_mon', cn="BEDROOM", ct='REAL'))
    c.execute("ALTER TABLE {tn} ADD COLUMN '{cn}' {ct}".format(tn='home_mon', cn="KITCHEN", ct='REAL'))

So you can see we have created an sql table wth the form;

/img/dragelec/sqldb_start.png

From the above you can see i created the table with false data but it only took <30min to populate with real data so a full page of data resembles;

/img/dragelec/sqldb_data.png

If anyone is interested the screenshots were taken from a gemini pda running android and the program used is SqlitePrime [2018-12-02 Sun] UPDATE SqlitePrime is no longer available on Google Play you can find it via aptoide or some of the other apk sites but …. i'd probably avoid it. As yet i haven't identified a suitable replacement for me.

decodexml - reading a currentcost meter

Although this is no longer done it may well get re-integrated should i purchase another clamp so the below is left for others should they want/need it and for myself so i don't start from scratch!

The electricity monitoring is done using a currentcost unit

/img/dragelec/currentcost_envi.png

this relies on a current transformer clamped around the mains incoming supply which broadcasts the data to receiver which in turn is connected to the Pi via a USB lead the data from this is output in XML format.

/img/dragelec/currentcost_xml.png

They now also sell a domestic gas adaptor gaSmart which i had intended to add at some point.


Link to old page: old dragelec org file as text

DONE - <2017-08-27 Sun> update document

CLOSED: [2018-08-28 Tue 11:45] this is in progress some elements are lacking as its under going a total re-write

DONE remove code duplication

CLOSED: [2017-12-24 Sun 09:40]

DONE remove data for car dash and re-write specifically for dragelec

CLOSED: [2017-12-26 Tue 10:40]

TODO add description of a dictionary and link to the earlier post written about them

TODO write up move of decode into main module


See also