Script om P1 metingen in MySQL database naar DSMR-Reader API te sturen

Door balk op vrijdag 27 januari 2017 13:19 - Reacties (5)
Categorie: -, Views: 7.471

Ik heb een script geschreven om P1 meet data uit een MySQL database te trekken en naar een DSMR-reader database te sturen.

/edit: ik heb de code een beetje aangepast want de overgang van winter naar zomertijd liep niet lekker. Dus nu maar handmatig de overgang ingevuld. Voor een jaar data moet je het script misschien wel drie keer draaien, telkens met een andere set datums. Op de nacht van de overgang van zomer naar wintertijd of andersom knip ik van middernacht tot zeven uur 's ochtends er uit. Gewoon om er zeker van te zijn dat het goed gaat.


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/python
import MySQLdb
import MySQLdb.cursors
import sys
from datetime import datetime
import time
import requests  # Tested with requests==2.9.1




db = MySQLdb.connect(host="localhost",    # your host, usually localhost
                     user="root",         # your username
                     passwd="xxx",  # your password
                     db="p1",cursorclass=MySQLdb.cursors.SSCursor)        # name of the data base

# you must create a Cursor object. It will let
#  you execute all the queries you need
cur = db.cursor()

nmin = 0
nmax = 5 # used for testing; I did not want to print 400,000 records every time :-)


# Select the latest meter readings from database
query = ("SELECT `p1_timestamp`, `p1_meterreading_in_1`, `p1_meterreading_in_2`, `p1_current_tariff`, `p1_current_power_in`, `p1_channel_1_timestamp`,`p1_channel_1_meterreading` FROM `p1_log` WHERE `p1_timestamp` BETWEEN %s AND %s ")


datum1 = datetime(2016,10,31,7)
datum2 = datetime(2017,2,1,0)


cur = db.cursor()
results = cur.execute(query, (datum1,datum2))

rows = cur.fetchone()
n = 0
while rows is not None:
    n = n+1

    if n >= nmin: #and n <= nmax:

            p1_timestamp = rows[0]
            p1_meterreading_in_1 = rows[1]
            p1_meterreading_in_2 = rows[2]
            p1_current_tariff = rows[3]
            p1_current_power_in = rows[4]
            p1_channel_1_timestamp = rows[5]
            p1_channel_1_meterreading = rows[6]
           
            # create timestamps in the right format
            eyear = p1_timestamp.strftime("%Y")[2:4]
            emonth = p1_timestamp.strftime("%m")
            eday = p1_timestamp.strftime("%d")
            ehour = p1_timestamp.strftime("%H")
            emin = p1_timestamp.strftime("%M")
            esec = p1_timestamp.strftime("%S")
            gyear = p1_channel_1_timestamp.strftime("%Y")[2:4]
            gmonth = p1_channel_1_timestamp.strftime("%m")
            gday = p1_channel_1_timestamp.strftime("%d")
            ghour = p1_channel_1_timestamp.strftime("%H")
            gmin = p1_channel_1_timestamp.strftime("%M")
            gsec = p1_channel_1_timestamp.strftime("%S")
            
           # create meter readings in the right format
            p1_meterreading_in_1 = "{:.3f}".format(p1_meterreading_in_1).rjust(9, '0')
            p1_meterreading_in_2 = "{:.3f}".format(p1_meterreading_in_2).rjust(9, '0')
            p1_current_power_in = "{:.3f}".format(p1_current_power_in).rjust(6, '0')
            p1_current_tariff =str(p1_current_tariff)
            p1_channel_1_meterreading = "{:.3f}".format(p1_channel_1_meterreading).rjust(9, '0')
            gtime = gyear+gmonth+gday+ghour+gmin+esec

            
           # create the telegram (DSMR 2.2!)
            telegram_string = ''.join([
                "/XMX5XMXABCE000043811\r\n",
                "\r\n",
                "0-0:1.0.0("+etime+")\r\n",
                "0-0:96.1.1(xxx)\r\n",
                "1-0:1.8.1("+p1_meterreading_in_1+"*kWh)\r\n",
                "1-0:1.8.2("+p1_meterreading_in_2+"*kWh)\r\n",
                "1-0:2.8.1(00000.000*kWh)\r\n",
                "1-0:2.8.2(00000.000*kWh)\r\n",
                "0-0:96.14.0(000"+p1_current_tariff+")\r\n",
                "1-0:1.7.0("+p1_current_power_in+"*kW)\r\n",
                "1-0:2.7.0(0000.00*kW)\r\n",
                "0-0:96.13.1()\r\n",
                "0-0:96.13.0()\r\n",
                "0-1:96.1.0(xxx)\r\n",
                "0-1:24.1.0(03)\r\n",
                "0-1:24.3.0("+gtime+")(00)(60)(1)(0-1:24.2.0)(m3)\r\n",
                "("+p1_channel_1_meterreading+")\r\n",
                "!000\r\n",



            ])

            #print telegram_string

                #Register telegram by simply sending it to the application with a POST request.
                response = requests.post(
                    'http://192.168.0.8/api/v1/datalogger/dsmrreading',
                    headers={'X-AUTHKEY': 'xxx'},
                    data={'telegram': telegram_string},

                # You will receive a status 200 when successful.
                if response.status_code != 200:
                    # Or you will find the error (hint) in the reponse body on failure.
                    print('Error: {}'.format(response.text))

                
    #            print "end of telegram: ", n


    rows = cur.fetchone()
    #rows = cur.fetchmany(size=100)
cur.close()
db.close()

Thermodynamisch model van je huis

Door balk op woensdag 18 januari 2017 02:29 - Reageren is niet meer mogelijk
Categorie: -, Views: 2.088

Ik wil in deze post een theoretisch thermodynamisch model beschrijven van een huis. Wellicht kan iemand dit gebruiken om z'n eigen thermostaat te tunen. Let wel: ik heb dit niet zelf geïmplementeerd!

Warmtebalans

Over elk object kun je een wamtebalans opstellen, dus ook over een huis:

code:
1
Qin - Quit = accumulatie , deltaQ, toename van wamteinhoud (1)


Waarbij Q = warmtestroom [Watt]
Wat? Alles wat er in gaat, en er niet uit gaat, hoopt er in op. Als je huis 15°C is, heb je veel energie nodig om je huis en alles er in op te warmen. Als je huis op temperatuur is hoeft de cv ketel maar een beetje te stoken. Dat komt omdat deltaQ dan 0 is. Er is geen toename meer van de warmteinhoud van je huis. Alle warmte die je in je huis stopt verlies je ook weer aan de omgeving.

Warmteverlies Quit

Warmteverlies is een functie van drie factoren:

code:
1
Quit = U * A * deltaT (2)


Waarbij
  • U = warmteoverdrachtscoefficient [Joule/m2/°C], afhankelijk van hoe goed je huis is geïsoleerd en van de windsnelheid buiten, en onbekend.
  • A = oppervlak van je huis [m2], ligt vast (tenzij je een verbouwing uitvoert of een extra kamer gaat verwarmen)
  • deltaT = temperatuur verschil tussen binnen en buiten [°C], kun je meten
  • Quit = warmteverlies [W]
Hoe kunnen we Quit en U bepalen?

Warmtetoevoer [Qin]

Wanneer een huis in steady-state is (constante temperatuur), zal Quit gelijk zijn aan Qin volgens (1). En Qin kun je berekenen aan de hand van het gasverbruik! Tijdens een periode van constante temperatuur dien je het verbruik te meten, en de buitentemperatuur. De energetische onderwaarde (LHV) van Slochters aardgas is 31,65 MJ/m3. Dus als je in twee uur 0,1 m3 hebt verbruikt komt dat neer op een gasverbruik van 440 Watt. Bij een rendement van de ketel van 107% (ja dat kan!) heb je dus een warmtetoevoer Qin van 470 Watt. En dat is ook je Quit. Doe hetzelfde bij een andere kamertemperatuur en bij voorkeur met behulp van een stookseizoen aan data. Zorg dat je geen douche of kookactiviteiten hebt tijdens de meting.

Warmteoverdracht U*A

Bereken nu voor elk datapunt, met behulp van de binnen- en buitentemperatuur. Daarmee kun je U*A berekenen. Je zult zien dat dit geen constante is. Als het waait zal je meer warmte verliezen. Dus eigenlijk wil je voor elk datapunt ook de windsnelheid wx hebben. Die kun je met de wunderground API binnentrekken of zelf meten.
code:
1
Q= U*A*c*wx * deltaT

zou dan moeten kloppen. Hier is c een empirische factor.

Als je je warmteoverdracht kunt voorspellen weet je dus ook hoeveel energie je verliest op een willekeurige dag.

Accumulatie

Hoeveel warmte heb je nodig om van de ene stabiele temperatuur naar de andere te gaan? Je moet een deel van de lucht in het huis opwarmen. Bijvoorbeeld de woonkamer en keuken naar 20°C en de overige vertrekken naar gemiddeld 18°C. De warmte capaciteit Cp van droge lucht is 1,006 kJ/kg/°C, de dichtheid van droge lucht is in dit temperatuur gebied ongeveer 1,21 kg/m3. Dus om 100 m3 droge lucht 5°C op te warmen heb je 608,6 kJoule nodig. Als je dit in een half uur doet is dat 338 Watt. Maar lucht is niet droog. Lucht van 20°C en 60% vochtigheid bevat 0,010 kg waterdamp per kubieke meter. Dat is 1 kg in onze ruimte van 100 m3 en kost 9300 kJ om 5°C op te warmen. Als die hoeveelheid energie in een half uur aanvoert is dat 5 Watt.

Zo kun je ook verder gaan voor muren, ramen, waterbedden en andere grote objecten.

Toepassing

Wat kun je hier nu mee?
  1. Een schatting maken van de tijd die een ketel nodig heeft om bij een vast vermogen een huis op te warmen. Of
  2. Een schatting maken van het benodigde vermogen van de ketel om in een bepaalde tijd het huis op te warmen.
En dat natuurlijk als functie van de buitentemperatuur, binnentemperatuur, luchtvochtigheid en windsnelheid.


code:
1
Afgegeven vermogen Qin [W] = warmteverlies Quit [W] + opwarmwarmte Hacc [J] / opwarmtijd t [s]



Het hangt af van je ketel of je een vermogen kunt regelen zodat je met een vaste opwarmtijd kunt werken, of dat je ketel volle bak gaat bij warmtevraag (aan/uit regeling bijvoorbeeld), of volgens een voorspelbare curve.

Ik hoop dat dit wat inzicht geeft in huis tuin en keuken thermodynamica en dat iemand zijn of haar voordeel er mee kan doen. Vragen? Opmerkingen? Onduidelijkheden?

NAS aan en uit wanneer MacBook aan en uit is

Door balk op zaterdag 7 januari 2017 13:50 - Reacties (10)
Categorie: -, Views: 6.319

Ik heb een Intel D510MO met twee HDD's draaiend op Debian. Dit ding is vooral een backup server voor de MacBook die hier in huis rondslingert. Het verbruik is ongeveer 20W en dat zijn natuurlijk weggegooide wattjes wanneer we slapen of werken.

Vanaf de Mac stuur ik elk uur een incremental backup met behulp van CCC naar de NAS. Het ene uur grote bestanden naar een share. Het andere uur kleine bestanden naar een image op een share. Kleine files? zaken als de Aperture library van 90 GB en enkele 100.000en files. Grote files? zaken als de raw foto bestanden.

Ik had eens ergens een script vandaan gehaald dat zorgde dat de NAS automatisch aan gaat als een bepaalde computer aan gaat, aan blijft als deze aan is, en weer uit gaat als die computer uit gaat. Bron is weg, dus ik herhaal hier schaamteloos de scriptjes.

1. Wake on Lan

In het BIOS van mijn NAS moest ik Wake On Lan activeren.

2. Wek de NAS wanneer MacBook ontwaakt

Met behulp van Sleepwatcher laat ik een script draaien wanneer de laptop wakker wordt. Dit staat in het bestand ~/.wakeup.

code:
1
2
3
4
5
6
7
8
9
#!/bin/bash


/usr/bin/perl /path/to/wol.pl --mac xx:xx:xx:xx:xx:xx

/bin/sleep 120

# vul IP van server in
/usr/bin/ssh 192.x.x.x '/bin/echo $(/bin/date +%s)  > /path/to/folder/wake/upmark'



Dit [url=]http://www.cpan.org/authors/id/S/SR/SRAMKI/]Wake on lan script[/] heb je nodig om met perl de NAS te WoL'en. Dit script heeft enkele dependencies. Installeer die ook.

Op de NAS moet je ook een (door de user beschrijfbare) directory aanmaken. Die van mij staat in ~/wake. Maak daarin een bestand upmark:
touch ~/wake/upmark

Bovenstaand script zal de NAS wakker schudden en twee minuten later de tijd schrijven naar ~/wake/upmark.

3. Hou de NAS wakker (kant van de Mac)

Ik heb op de Mac het volgende script: ticker.sh

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

ip="192.168.0.NAS" # IP of NAS

if ! ping -c 1 -W 5 "$ip" &>/dev/null ; then

echo "$ip is down, they're all going to laugh at you!"
/usr/bin/perl /path/to/wol.pl --mac xx:xx:xx:xx:xx:xx
/bin/sleep 120
else
echo "$ip is up"
fi

/usr/bin/ssh 192.168.0.NAS '/bin/echo $(/bin/date +%s)  > /path/to/wake/upmark'
#$(/bin/date +%s)


Met behulp van Launcontrol roep ik elk kwartier dit script aan:
ticker.sh

4. Hou de NAS wakker (kant van de NAS)

Op de NAS, installeer pm-utils en test de correcte werking. Het laat je NAS hibernaten, dit schrijft de inhoud van je RAM naar schijf en de NAS gaat helemaal uit.

Creëer het bestand /path/to/wake/keepawake.sh

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

file="/path/to/wake/upmark"
LOGPATH="/path/to/wake/log_wake.log"

timestamp() {
  /bin/date
}

mactime=$(/bin/cat "$file")
now=$(/bin/date +%s)

#deltat=`/usr/bin/expr $(/bin/date +%s)-$mactime`
deltat=$(($now  - $mactime))
limit=1200

/bin/echo $deltat
/bin/echo $limit

if (( deltat > limit ));
then
        # hibernate
        /bin/echo "$(timestamp): system hibernated" >> $LOGPATH
#       /bin/systemctl hibernate
        /usr/bin/sudo /usr/sbin/pm-hibernate
        exit
else
        # do nothing
        
        /bin/echo "$(timestamp): system kept awake, delta is $deltat" >> $LOGPATH
        exit
fi


Als user:
crontab -e


code:
1
5,20,35,50 * * * * /path/to/wake/keepawake.sh


Dit roept elk uur, 5 minuten nadat er een ticker binnen is gekomen van de Mac, het script op dat de huidige tijd met de ticker tijd vergelijkt. Is er geen ticker binnengekomen? Dan is de Mac offline en kan de NAS gaan slapen.