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: 4.698

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()

Volgende: CO2 Meter met MH-Z19 09-04 CO2 Meter met MH-Z19
Volgende: Thermodynamisch model van je huis 18-01 Thermodynamisch model van je huis

Reacties


Door Tweakers user siepeltjuh, vrijdag 27 januari 2017 18:50

Is er een specifieke reden waarom je deze volgorde aanhoudt:
Telegram -> MySQL -> Telegram -> DSMReader -> PostgreSQL ?

Zonder de achterliggende reden lijkt het wat veel heen en weer gesleep met data.

Door Tweakers user Mattie112, vrijdag 27 januari 2017 22:59

Ik denk dat hij overstapt en dat dit dus een eenmalig script is :)

Door Tweakers user balk, zaterdag 28 januari 2017 11:35

Mattie112 schreef op vrijdag 27 januari 2017 @ 22:59:
Ik denk dat hij overstapt en dat dit dus een eenmalig script is :)
Zo is het maar net! Een jaar geleden heb ik mijn P1 poort aangesloten en data opgeslagen, maar ik wist niet wat ik er mee moest. Recent kwam ik DSMR-reader tegen en besloot ik te migreren.

Script is overigens halverwege de nacht gestopt; komt nog een update.

Door Tweakers user Coffeemonster, dinsdag 31 januari 2017 14:08

Ik heb voor een project op mijn werk het python-script van smartmeterdashboard.nl gebruikt om de data van hun P1-reader op te slaan in een csv-file. Mij viel op dat er regelmatig incomplete p1-telegrammen binnenkomen. Deze lieten het script crashen met een error. Ik heb toen enkele snelle checks toegevoegd om onder meer te controleren of er geen afgebroken regels in het Telegram staan. Dit heb ik verder nog niet gecheckt, maar dat wil ik uiteindelijk bij mij thuis wel gaan gebruiken. Als je wil dan kan ik ergens deze week wel die checks voor je opzoeken.

Edit: Ik zie nu dat het hier om P1-data uit een database gaat. Wellicht dat dit voor de data in de MySQL-database minder relevant is, maar ik weet niet of jouw script en/of DSMR-reader goed met incomplete data om kan gaan.

[Reactie gewijzigd op dinsdag 31 januari 2017 14:18]


Door Tweakers user balk, dinsdag 31 januari 2017 17:56

Coffeemonster schreef op dinsdag 31 januari 2017 @ 14:08:
Ik heb voor een project op mijn werk het python-script van smartmeterdashboard.nl gebruikt om de data van hun P1-reader op te slaan in een csv-file. Mij viel op dat er regelmatig incomplete p1-telegrammen binnenkomen. Deze lieten het script crashen met een error. Ik heb toen enkele snelle checks toegevoegd om onder meer te controleren of er geen afgebroken regels in het Telegram staan. Dit heb ik verder nog niet gecheckt, maar dat wil ik uiteindelijk bij mij thuis wel gaan gebruiken. Als je wil dan kan ik ergens deze week wel die checks voor je opzoeken.

Edit: Ik zie nu dat het hier om P1-data uit een database gaat. Wellicht dat dit voor de data in de MySQL-database minder relevant is, maar ik weet niet of jouw script en/of DSMR-reader goed met incomplete data om kan gaan.
Ik ben ook begonnen met het script van die site, wel een oudere versie. Aardig verbouwd omdat de database veel te groot werd; er werd veel te veel info opgeslagen. Halverwege vorig jaar ben ik naar een draadloze uitlezing overgestapt, met dit dingetje. De esp software daarbij doet een CRC wat halve telegrammen weert.

Desalniettemin struikelde dit script een paar keer over een leeg datumveld. In de 300,000 velden zit vast ergens een fout maar ik moet het nog even afmaken. Aandacht is weer door iets anders opgeslokt. :)

[Reactie gewijzigd op dinsdag 31 januari 2017 17:57]


Reageren is niet meer mogelijk