| 1 |
raymond |
1 |
#!python3
|
|
|
2 |
# P1 Datalogger
|
|
|
3 |
# $Revision: 9 $
|
|
|
4 |
# $Author: raymond $
|
|
|
5 |
# $Date: 2015-09-06 13:19:50 +0200 (zo, 06 sep 2015) $
|
|
|
6 |
# Copyright (c) 2015 R. V. Slegers
|
|
|
7 |
#
|
|
|
8 |
# Although there is a explicit copyright on this sourcecode, anyone may use it freely under a
|
|
|
9 |
# "Creative Commons Naamsvermelding-NietCommercieel-GeenAfgeleideWerken 3.0 Nederland" licentie.
|
|
|
10 |
# Please check http://creativecommons.org/licenses/by-nc-nd/3.0/nl/ for details
|
|
|
11 |
#
|
|
|
12 |
# This software is provided as is and comes with absolutely no warranty.
|
|
|
13 |
# The author is not responsible or liable (direct or indirect) to anyone for the use or misuse of this software.
|
|
|
14 |
# Any person using this software does so entirely at his/her own risk.
|
|
|
15 |
# That person bears sole responsibility and liability for any claims or actions, legal or civil, arising from such use.
|
|
|
16 |
# If you believe this software is in breach of anyone's copyright you will inform the author immediately so the offending material
|
|
|
17 |
# can be removed upon receipt of proof of copyright for that material.
|
|
|
18 |
#
|
|
|
19 |
# Dependend on Python 3.x and Python 3.x packages: PySerial 2.5
|
|
|
20 |
#
|
|
|
21 |
|
|
|
22 |
progname='P1.py'
|
|
|
23 |
version = "v0.73b"
|
|
|
24 |
import_db = True
|
|
|
25 |
import sys
|
|
|
26 |
import serial
|
|
|
27 |
import datetime
|
|
|
28 |
import csv
|
|
|
29 |
import os
|
|
|
30 |
import locale
|
|
|
31 |
import socket
|
|
|
32 |
import http.client
|
|
|
33 |
import urllib.parse
|
|
|
34 |
import argparse
|
|
|
35 |
import configparser
|
|
|
36 |
import glob
|
|
|
37 |
|
|
|
38 |
socket.setdefaulttimeout(30)
|
|
|
39 |
MySQL_loaded = True
|
|
|
40 |
try:
|
|
|
41 |
import mysql.connector
|
|
|
42 |
except ImportError:
|
|
|
43 |
MySQL_loaded=False
|
|
|
44 |
from time import sleep
|
|
|
45 |
|
|
|
46 |
#####################################################################
|
|
|
47 |
# pvoutput.org system parameters
|
|
|
48 |
#####################################################################
|
|
|
49 |
pvo_url = 'http://pvoutput.org/service/r2/addstatus.jsp'
|
|
|
50 |
#####################################################################
|
|
|
51 |
|
|
|
52 |
class P1_ChannelData:
|
|
|
53 |
def __init__(self, id=0, type_id=0, type_desc='', equipment_id='', timestamp='0000-00-00 00:00:00', meterreading=0.0, unit='', valveposition=0):
|
|
|
54 |
self.id = id
|
|
|
55 |
self.type_id = type_id
|
|
|
56 |
self.type_desc = type_desc
|
|
|
57 |
self.equipment_id = equipment_id
|
|
|
58 |
self.timestamp = timestamp
|
|
|
59 |
self.meterreading = meterreading
|
|
|
60 |
self.unit = unit
|
|
|
61 |
self.valveposition = valveposition
|
|
|
62 |
|
|
|
63 |
def scan_serial():
|
|
|
64 |
# scan for available ports. return a list of tuples (num, name)
|
|
|
65 |
""" Lists serial port names
|
|
|
66 |
|
|
|
67 |
:raises EnvironmentError:
|
|
|
68 |
On unsupported or unknown platforms
|
|
|
69 |
:returns:
|
|
|
70 |
A list of the serial ports available on the system
|
|
|
71 |
"""
|
|
|
72 |
if sys.platform.startswith('win'):
|
|
|
73 |
ports = ['COM%s' % (i + 1) for i in range(256)]
|
|
|
74 |
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
|
|
|
75 |
# this excludes your current terminal "/dev/tty"
|
|
|
76 |
ports = glob.glob('/dev/tty[A-Za-z]*')
|
|
|
77 |
elif sys.platform.startswith('darwin'):
|
|
|
78 |
ports = glob.glob('/dev/tty.*')
|
|
|
79 |
else:
|
|
|
80 |
raise EnvironmentError('Unsupported platform')
|
|
|
81 |
|
|
|
82 |
port_exceptions = ['/dev/ttyprintk','dev/ttyprintk']
|
|
|
83 |
for port in port_exceptions:
|
|
|
84 |
if port in ports:
|
|
|
85 |
ports.remove(port)
|
|
|
86 |
|
|
|
87 |
available = []
|
|
|
88 |
for port in ports:
|
|
|
89 |
try:
|
|
|
90 |
s = serial.Serial(port)
|
|
|
91 |
s.close()
|
|
|
92 |
available.append(port)
|
|
|
93 |
except (OSError, serial.SerialException):
|
|
|
94 |
pass
|
|
|
95 |
if not available:
|
|
|
96 |
available.append('Helaas geen seriele poorten gevonden')
|
|
|
97 |
return available
|
|
|
98 |
|
|
|
99 |
################
|
|
|
100 |
#Error display #
|
|
|
101 |
################
|
|
|
102 |
def show_error():
|
|
|
103 |
ft = sys.exc_info()[0]
|
|
|
104 |
fv = sys.exc_info()[1]
|
|
|
105 |
print("Fout type: %s" % ft )
|
|
|
106 |
print("Fout waarde: %s" % fv )
|
|
|
107 |
return
|
|
|
108 |
|
|
|
109 |
################
|
|
|
110 |
#Scherm output #
|
|
|
111 |
################
|
|
|
112 |
def print_p1_telegram():
|
|
|
113 |
print ("---------------------------------------------------------------------------------------")
|
|
|
114 |
print ("P1 telegram ontvangen op: %s" % p1_timestamp)
|
|
|
115 |
if p1_meter_supplier == "KMP":
|
|
|
116 |
print ("Meter fabrikant: Kamstrup")
|
|
|
117 |
elif p1_meter_supplier == "ISk":
|
|
|
118 |
print ("Meter fabrikant: IskraEmeco")
|
|
|
119 |
elif p1_meter_supplier == "XMX":
|
|
|
120 |
print ("Meter fabrikant: Xemex")
|
|
|
121 |
elif p1_meter_supplier == "KFM":
|
|
|
122 |
print ("Meter fabrikant: Kaifa")
|
|
|
123 |
else:
|
|
|
124 |
print ("Meter fabrikant: Niet herkend")
|
|
|
125 |
print ("Meter informatie: %s" % p1_header )
|
|
|
126 |
print (" 0. 2. 8 - DSMR versie: %s" % p1_dsmr_version )
|
|
|
127 |
print ("96. 1. 1 - Meternummer Elektriciteit: %s" % p1_equipment_id )
|
|
|
128 |
print (" 1. 8. 1 - Meterstand Elektriciteit levering (T1/Laagtarief): %0.3f %s" % (p1_meterreading_in_1,p1_unitmeterreading_in_1) )
|
|
|
129 |
print (" 1. 8. 2 - Meterstand Elektriciteit levering (T2/Normaaltarief): %0.3f %s" % (p1_meterreading_in_2,p1_unitmeterreading_in_2) )
|
|
|
130 |
print (" 2. 8. 1 - Meterstand Elektriciteit teruglevering (T1/Laagtarief): %0.3f %s" % (p1_meterreading_out_1,p1_unitmeterreading_out_1) )
|
|
|
131 |
print (" 2. 8. 2 - Meterstand Elektriciteit teruglevering (T2/Normaaltarief): %0.3f %s" % (p1_meterreading_out_2,p1_unitmeterreading_out_2) )
|
|
|
132 |
print ("96.14. 0 - Actueel tarief Elektriciteit: %d" % p1_current_tariff )
|
|
|
133 |
print (" 1. 7. 0 - Actueel vermogen Electriciteit levering (+P): %0.3f %s" % (p1_current_power_in,p1_unit_current_power_in) )
|
|
|
134 |
print (" 2. 7. 0 - Actueel vermogen Electriciteit teruglevering (-P): %0.3f %s" % (p1_current_power_out,p1_unit_current_power_out) )
|
|
|
135 |
print ("17. 0. 0 - Actuele doorlaatwaarde Elektriciteit: %0.3f %s" % (p1_current_threshold,p1_unit_current_threshold) )
|
|
|
136 |
print ("96. 3.10 - Actuele schakelaarpositie Elektriciteit: %s" % p1_current_switch_position )
|
|
|
137 |
print ("96. 7.21 - Aantal onderbrekingen Elektriciteit: %s" % p1_powerfailures )
|
|
|
138 |
print ("96. 7. 9 - Aantal lange onderbrekingen Elektriciteit: %s" % p1_long_powerfailures )
|
|
|
139 |
print ("99.97. 0 - Lange onderbrekingen Elektriciteit logboek: %s" % p1_long_powerfailures_log )
|
|
|
140 |
print ("32.32. 0 - Aantal korte spanningsdalingen Elektriciteit in fase 1: %s" % p1_voltage_sags_l1 )
|
|
|
141 |
print ("52.32. 0 - Aantal korte spanningsdalingen Elektriciteit in fase 2: %s" % p1_voltage_sags_l2 )
|
|
|
142 |
print ("72.32. 0 - Aantal korte spanningsdalingen Elektriciteit in fase 3: %s" % p1_voltage_sags_l3 )
|
|
|
143 |
print ("32.36. 0 - Aantal korte spanningsstijgingen Elektriciteit in fase 1: %s" % p1_voltage_swells_l1 )
|
|
|
144 |
print ("52.36. 0 - Aantal korte spanningsstijgingen Elektriciteit in fase 2: %s" % p1_voltage_swells_l2 )
|
|
|
145 |
print ("72.36. 0 - Aantal korte spanningsstijgingen Elektriciteit in fase 3: %s" % p1_voltage_swells_l3 )
|
|
|
146 |
print ("31. 7. 0 - Instantane stroom Elektriciteit in fase 1: %0.3f %s" % (p1_instantaneous_current_l1,p1_unit_instantaneous_current_l1) )
|
|
|
147 |
print ("51. 7. 0 - Instantane stroom Elektriciteit in fase 2: %0.3f %s" % (p1_instantaneous_current_l2,p1_unit_instantaneous_current_l2) )
|
|
|
148 |
print ("71. 7. 0 - Instantane stroom Elektriciteit in fase 3: %0.3f %s" % (p1_instantaneous_current_l3,p1_unit_instantaneous_current_l3) )
|
|
|
149 |
print ("32. 7. 0 - Spanning Elektriciteit in fase 1: %0.3f %s" % (p1_voltage_l1,p1_unit_voltage_l1) )
|
|
|
150 |
print ("52. 7. 0 - Spanning Elektriciteit in fase 2: %0.3f %s" % (p1_voltage_l2,p1_unit_voltage_l2) )
|
|
|
151 |
print ("72. 7. 0 - Spanning Elektriciteit in fase 3: %0.3f %s" % (p1_voltage_l3,p1_unit_voltage_l3) )
|
|
|
152 |
print ("21. 7. 0 - Instantaan vermogen Elektriciteit levering (+P) in fase 1: %0.3f %s" % (p1_instantaneous_active_power_in_l1,p1_unit_instantaneous_active_power_in_l1) )
|
|
|
153 |
print ("41. 7. 0 - Instantaan vermogen Elektriciteit levering (+P) in fase 2: %0.3f %s" % (p1_instantaneous_active_power_in_l2,p1_unit_instantaneous_active_power_in_l2) )
|
|
|
154 |
print ("61. 7. 0 - Instantaan vermogen Elektriciteit levering (+P) in fase 3: %0.3f %s" % (p1_instantaneous_active_power_in_l3,p1_unit_instantaneous_active_power_in_l3) )
|
|
|
155 |
print ("22. 7. 0 - Instantaan vermogen Elektriciteit teruglevering (-P) in fase 1: %0.3f %s" % (p1_instantaneous_active_power_out_l1,p1_unit_instantaneous_active_power_out_l1) )
|
|
|
156 |
print ("42. 7. 0 - Instantaan vermogen Elektriciteit teruglevering (-P) in fase 2: %0.3f %s" % (p1_instantaneous_active_power_out_l2,p1_unit_instantaneous_active_power_out_l2) )
|
|
|
157 |
print ("62. 7. 0 - Instantaan vermogen Elektriciteit teruglevering (-P) in fase 3: %0.3f %s" % (p1_instantaneous_active_power_out_l3,p1_unit_instantaneous_active_power_out_l3) )
|
|
|
158 |
print ("96.13. 1 - Bericht code: %s" % p1_message_code )
|
|
|
159 |
print ("96.13. 0 - Bericht tekst: %s" % p1_message_text )
|
|
|
160 |
channellist = [p1_channel_1, p1_channel_2, p1_channel_3, p1_channel_4]
|
|
|
161 |
for channel in channellist:
|
|
|
162 |
if channel.id != 0:
|
|
|
163 |
print ("MBus Meterkanaal: %s" % channel.id )
|
|
|
164 |
print ("24. 1. 0 - Productsoort: %s (%s)" % (channel.type_id, channel.type_desc) )
|
|
|
165 |
print ("91. 1. 0 - Meternummer %s: %s" % (channel.type_desc, channel.equipment_id) )
|
|
|
166 |
if p1_dsmr_version != "40":
|
|
|
167 |
print ("24. 3. 0 - Tijdstip meterstand %s levering: %s" % (channel.type_desc, channel.timestamp) )
|
|
|
168 |
print ("24. 3. 0 - Meterstand %s levering: %0.3f %s" % (channel.type_desc, channel.meterreading, channel.unit) )
|
|
|
169 |
else:
|
|
|
170 |
print ("24. 2. 1 - Tijdstip meterstand %s levering: %s" % (channel.type_desc, channel.timestamp) )
|
|
|
171 |
print ("24. 2. 1 - Meterstand %s levering: %0.3f %s" % (channel.type_desc, channel.meterreading, channel.unit) )
|
|
|
172 |
print ("24. 4. 0 - Actuele kleppositie %s: %s" % (channel.type_desc,channel.valveposition) )
|
|
|
173 |
print ("Einde P1 telegram" )
|
|
|
174 |
return
|
|
|
175 |
################
|
|
|
176 |
#Csv output #
|
|
|
177 |
################
|
|
|
178 |
def csv_p1_telegram():
|
|
|
179 |
#New filename every day
|
|
|
180 |
csv_filename=datetime.datetime.strftime(datetime.datetime.today(), "P1_"+"%Y-%m-%d_"+str(log_interval*10)+"s.csv" )
|
|
|
181 |
try:
|
|
|
182 |
#If csv_file exists: open it
|
|
|
183 |
csv_file=open(csv_filename, 'rt')
|
|
|
184 |
csv_file.close()
|
|
|
185 |
csv_file=open(csv_filename, 'at', newline='', encoding="utf-8")
|
|
|
186 |
writer = csv.writer(csv_file, dialect='excel', delimiter=';', quoting=csv.QUOTE_NONNUMERIC)
|
|
|
187 |
except IOError:
|
|
|
188 |
#Otherwise: create it
|
|
|
189 |
csv_file=open(csv_filename, 'wt', newline='', encoding="utf-8")
|
|
|
190 |
writer = csv.writer(csv_file, dialect='excel', delimiter=';', quoting=csv.QUOTE_NONNUMERIC)
|
|
|
191 |
#Write csv-header
|
|
|
192 |
writer.writerow([
|
|
|
193 |
'p1_timestamp',
|
|
|
194 |
'p1_meter_supplier',
|
|
|
195 |
'p1_header',
|
|
|
196 |
'p1_dsmr_version',
|
|
|
197 |
'p1_equipment_id',
|
|
|
198 |
'p1_meterreading_in_1',
|
|
|
199 |
'p1_unitmeterreading_in_1',
|
|
|
200 |
'p1_meterreading_in_2',
|
|
|
201 |
'p1_unitmeterreading_in_2',
|
|
|
202 |
'p1_meterreading_out_1',
|
|
|
203 |
'p1_unitmeterreading_out_1',
|
|
|
204 |
'p1_meterreading_out_2',
|
|
|
205 |
'p1_unitmeterreading_out_2',
|
|
|
206 |
'p1_current_tariff',
|
|
|
207 |
'p1_current_power_in',
|
|
|
208 |
'p1_unit_current_power_in',
|
|
|
209 |
'p1_current_power_out',
|
|
|
210 |
'p1_unit_current_power_out',
|
|
|
211 |
'p1_current_threshold',
|
|
|
212 |
'p1_unit_current_threshold',
|
|
|
213 |
'p1_current_switch_position',
|
|
|
214 |
'p1_powerfailures',
|
|
|
215 |
'p1_long_powerfailures',
|
|
|
216 |
'p1_long_powerfailures_log',
|
|
|
217 |
'p1_voltage_sags_l1',
|
|
|
218 |
'p1_voltage_sags_l2',
|
|
|
219 |
'p1_voltage_sags_l3',
|
|
|
220 |
'p1_voltage_swells_l1',
|
|
|
221 |
'p1_voltage_swells_l2',
|
|
|
222 |
'p1_voltage_swells_l3',
|
|
|
223 |
'p1_instantaneous_current_l1',
|
|
|
224 |
'p1_unit_instantaneous_current_l1',
|
|
|
225 |
'p1_instantaneous_current_l2',
|
|
|
226 |
'p1_unit_instantaneous_current_l2',
|
|
|
227 |
'p1_instantaneous_current_l3',
|
|
|
228 |
'p1_unit_instantaneous_current_l3',
|
|
|
229 |
'p1_voltage_l1',
|
|
|
230 |
'p1_unit_voltage_l1',
|
|
|
231 |
'p1_voltage_l2',
|
|
|
232 |
'p1_unit_voltage_l2',
|
|
|
233 |
'p1_voltage_l3',
|
|
|
234 |
'p1_unit_voltage_l3',
|
|
|
235 |
'p1_instantaneous_active_power_in_l1',
|
|
|
236 |
'p1_unit_instantaneous_active_power_in_l1',
|
|
|
237 |
'p1_instantaneous_active_power_in_l2',
|
|
|
238 |
'p1_unit_instantaneous_active_power_in_l2',
|
|
|
239 |
'p1_instantaneous_active_power_in_l3',
|
|
|
240 |
'p1_unit_instantaneous_active_power_in_l3',
|
|
|
241 |
'p1_instantaneous_active_power_out_l1',
|
|
|
242 |
'p1_unit_instantaneous_active_power_out_l1',
|
|
|
243 |
'p1_instantaneous_active_power_out_l2',
|
|
|
244 |
'p1_unit_instantaneous_active_power_out_l2',
|
|
|
245 |
'p1_instantaneous_active_power_out_l3',
|
|
|
246 |
'p1_unit_instantaneous_active_power_out_l3',
|
|
|
247 |
'p1_message_code',
|
|
|
248 |
'p1_message_text',
|
|
|
249 |
'p1_channel_1_id',
|
|
|
250 |
'p1_channel_1_type_id',
|
|
|
251 |
'p1_channel_1_type_desc',
|
|
|
252 |
'p1_channel_1_equipment_id',
|
|
|
253 |
'p1_channel_1_timestamp',
|
|
|
254 |
'p1_channel_1_meterreading',
|
|
|
255 |
'p1_channel_1_unit',
|
|
|
256 |
'p1_channel_1_valveposition',
|
|
|
257 |
'p1_channel_2_id',
|
|
|
258 |
'p1_channel_2_type_id',
|
|
|
259 |
'p1_channel_2_type_desc',
|
|
|
260 |
'p1_channel_2_equipment_id',
|
|
|
261 |
'p1_channel_2_timestamp',
|
|
|
262 |
'p1_channel_2_meterreading',
|
|
|
263 |
'p1_channel_2_unit',
|
|
|
264 |
'p1_channel_2_valveposition',
|
|
|
265 |
'p1_channel_3_id',
|
|
|
266 |
'p1_channel_3_type_id',
|
|
|
267 |
'p1_channel_3_type_desc',
|
|
|
268 |
'p1_channel_3_equipment_id',
|
|
|
269 |
'p1_channel_3_timestamp',
|
|
|
270 |
'p1_channel_3_meterreading',
|
|
|
271 |
'p1_channel_3_unit',
|
|
|
272 |
'p1_channel_3_valveposition',
|
|
|
273 |
'p1_channel_4_id',
|
|
|
274 |
'p1_channel_4_type_id',
|
|
|
275 |
'p1_channel_4_type_desc',
|
|
|
276 |
'p1_channel_4_equipment_id',
|
|
|
277 |
'p1_channel_4_timestamp',
|
|
|
278 |
'p1_channel_4_meterreading',
|
|
|
279 |
'p1_channel_4_unit',
|
|
|
280 |
'p1_channel_4_valveposition' ])
|
|
|
281 |
|
|
|
282 |
print ("P1 telegram in %s gelogd op: %s" % (csv_filename, p1_timestamp) )
|
|
|
283 |
writer.writerow([
|
|
|
284 |
p1_timestamp,
|
|
|
285 |
p1_meter_supplier,
|
|
|
286 |
p1_header,
|
|
|
287 |
p1_dsmr_version,
|
|
|
288 |
p1_equipment_id,
|
|
|
289 |
p1_meterreading_in_1, p1_unitmeterreading_in_1,
|
|
|
290 |
p1_meterreading_in_2, p1_unitmeterreading_in_2,
|
|
|
291 |
p1_meterreading_out_1,p1_unitmeterreading_out_1,
|
|
|
292 |
p1_meterreading_out_2,p1_unitmeterreading_out_2,
|
|
|
293 |
p1_current_tariff,
|
|
|
294 |
p1_current_power_in,p1_unit_current_power_in,
|
|
|
295 |
p1_current_power_out,p1_unit_current_power_out,
|
|
|
296 |
p1_current_threshold,p1_unit_current_threshold,
|
|
|
297 |
p1_current_switch_position,
|
|
|
298 |
p1_powerfailures,
|
|
|
299 |
p1_long_powerfailures,
|
|
|
300 |
p1_long_powerfailures_log,
|
|
|
301 |
p1_voltage_sags_l1,
|
|
|
302 |
p1_voltage_sags_l2,
|
|
|
303 |
p1_voltage_sags_l3,
|
|
|
304 |
p1_voltage_swells_l1,
|
|
|
305 |
p1_voltage_swells_l2,
|
|
|
306 |
p1_voltage_swells_l3,
|
|
|
307 |
p1_instantaneous_current_l1, p1_unit_instantaneous_current_l1,
|
|
|
308 |
p1_instantaneous_current_l2, p1_unit_instantaneous_current_l2,
|
|
|
309 |
p1_instantaneous_current_l3, p1_unit_instantaneous_current_l3,
|
|
|
310 |
p1_voltage_l1, p1_unit_voltage_l1,
|
|
|
311 |
p1_voltage_l2, p1_unit_voltage_l2,
|
|
|
312 |
p1_voltage_l3, p1_unit_voltage_l3,
|
|
|
313 |
p1_instantaneous_active_power_in_l1, p1_unit_instantaneous_active_power_in_l1,
|
|
|
314 |
p1_instantaneous_active_power_in_l2, p1_unit_instantaneous_active_power_in_l2,
|
|
|
315 |
p1_instantaneous_active_power_in_l3, p1_unit_instantaneous_active_power_in_l3,
|
|
|
316 |
p1_instantaneous_active_power_out_l1, p1_unit_instantaneous_active_power_out_l1,
|
|
|
317 |
p1_instantaneous_active_power_out_l2, p1_unit_instantaneous_active_power_out_l2,
|
|
|
318 |
p1_instantaneous_active_power_out_l3, p1_unit_instantaneous_active_power_out_l3,
|
|
|
319 |
p1_message_code,
|
|
|
320 |
p1_message_text,
|
|
|
321 |
p1_channel_1.id,
|
|
|
322 |
p1_channel_1.type_id,
|
|
|
323 |
p1_channel_1.equipment_id,
|
|
|
324 |
p1_channel_1.timestamp,
|
|
|
325 |
p1_channel_1.meterreading, p1_channel_1.unit,
|
|
|
326 |
p1_channel_1.valveposition,
|
|
|
327 |
p1_channel_2.id,
|
|
|
328 |
p1_channel_2.type_id,
|
|
|
329 |
p1_channel_2.equipment_id,
|
|
|
330 |
p1_channel_2.timestamp,
|
|
|
331 |
p1_channel_2.meterreading, p1_channel_2.unit,
|
|
|
332 |
p1_channel_2.valveposition,
|
|
|
333 |
p1_channel_3.id,
|
|
|
334 |
p1_channel_3.type_id,
|
|
|
335 |
p1_channel_3.equipment_id,
|
|
|
336 |
p1_channel_3.timestamp,
|
|
|
337 |
p1_channel_3.meterreading, p1_channel_3.unit,
|
|
|
338 |
p1_channel_3.valveposition,
|
|
|
339 |
p1_channel_4.id,
|
|
|
340 |
p1_channel_4.type_id,
|
|
|
341 |
p1_channel_4.equipment_id,
|
|
|
342 |
p1_channel_4.timestamp,
|
|
|
343 |
p1_channel_4.meterreading, p1_channel_4.unit,
|
|
|
344 |
p1_channel_4.valveposition ])
|
|
|
345 |
csv_file.close()
|
|
|
346 |
|
|
|
347 |
return
|
|
|
348 |
|
|
|
349 |
################
|
|
|
350 |
#DB output #
|
|
|
351 |
################
|
|
|
352 |
ID = ''
|
|
|
353 |
def db_p1_telegram():
|
|
|
354 |
query = "insert into p1_log values (\'" + \
|
|
|
355 |
ID + "\',\'" + \
|
|
|
356 |
p1_timestamp + "\',\'" + \
|
|
|
357 |
str(p1_meterreading_in_1) + "\',\'" + \
|
|
|
358 |
str(p1_meterreading_in_2) + "\',\'" + \
|
|
|
359 |
str(p1_meterreading_out_1) + "\',\'" +\
|
|
|
360 |
str(p1_meterreading_out_2) + "\',\'" + \
|
|
|
361 |
str(p1_current_tariff) + "\',\'" + \
|
|
|
362 |
str(p1_current_power_in) + "\',\'" + \
|
|
|
363 |
str(p1_current_power_out) + "\',\'" + \
|
|
|
364 |
str(p1_channel_1.id) + "\',\'" + \
|
|
|
365 |
str(p1_channel_1.type_id) + "\',\'" + \
|
|
|
366 |
p1_channel_1.timestamp + "\',\'" + \
|
|
|
367 |
str(p1_channel_1.meterreading) + "\',\'" + \
|
|
|
368 |
p1_channel_1.unit + "\',\'" + \
|
|
|
369 |
str(p1_channel_2.id) + "\',\'" + \
|
|
|
370 |
str(p1_channel_2.type_id) + "\',\'" + \
|
|
|
371 |
p1_channel_2.timestamp + "\',\'" + \
|
|
|
372 |
str(p1_channel_2.meterreading) + "\',\'" + \
|
|
|
373 |
p1_channel_2.unit + "\',\'" + \
|
|
|
374 |
str(p1_channel_3.id) + "\',\'" + \
|
|
|
375 |
str(p1_channel_3.type_id) + "\',\'" + \
|
|
|
376 |
p1_channel_3.timestamp + "\',\'" + \
|
|
|
377 |
str(p1_channel_3.meterreading) + "\',\'" + \
|
|
|
378 |
p1_channel_3.unit + "\',\'" + \
|
|
|
379 |
str(p1_channel_4.id) + "\',\'" + \
|
|
|
380 |
str(p1_channel_4.type_id) + "\',\'" + \
|
|
|
381 |
p1_channel_4.timestamp + "\',\'" + \
|
|
|
382 |
str(p1_channel_4.meterreading) + "\',\'" + \
|
|
|
383 |
p1_channel_4.unit + "\')"
|
|
|
384 |
# print(query)
|
|
|
385 |
try:
|
|
|
386 |
db = mysql.connector.connect(user=p1_mysql_user, password=p1_mysql_passwd, host=p1_mysql_host, database=p1_mysql_db, get_warnings=True)
|
|
|
387 |
c = db.cursor()
|
|
|
388 |
c.execute (query)
|
|
|
389 |
db.commit()
|
|
|
390 |
print ("P1 telegram in database %s / %s gelogd op: %s" % (p1_mysql_host, p1_mysql_db, p1_timestamp) )
|
|
|
391 |
c.close()
|
|
|
392 |
db.close()
|
|
|
393 |
except:
|
|
|
394 |
show_error()
|
|
|
395 |
print ("Fout bij het openen van / schrijven naar database %s / %s. P1 Telegram wordt gelogd in csv-bestand." % (p1_mysql_host, p1_mysql_db))
|
|
|
396 |
csv_p1_telegram()
|
|
|
397 |
return
|
|
|
398 |
|
|
|
399 |
def db_p2_telegram():
|
|
|
400 |
query = "insert into p2_log values (\'" + \
|
|
|
401 |
ID + "\',\'" + \
|
|
|
402 |
p1_timestamp + "\',\'" + \
|
|
|
403 |
p1_meter_supplier + "\',\'" + \
|
|
|
404 |
p1_header + "\',\'" + \
|
|
|
405 |
p1_dsmr_version + "\',\'" + \
|
|
|
406 |
p1_equipment_id + "\',\'" + \
|
|
|
407 |
str(p1_meterreading_in_1) + "\',\'" + \
|
|
|
408 |
p1_unitmeterreading_in_1 + "\',\'" + \
|
|
|
409 |
str(p1_meterreading_in_2) + "\',\'" + \
|
|
|
410 |
p1_unitmeterreading_in_2 + "\',\'" + \
|
|
|
411 |
str(p1_meterreading_out_1) + "\',\'" +\
|
|
|
412 |
p1_unitmeterreading_out_1 + "\',\'" + \
|
|
|
413 |
str(p1_meterreading_out_2) + "\',\'" + \
|
|
|
414 |
p1_unitmeterreading_out_2 + "\',\'" + \
|
|
|
415 |
str(p1_current_tariff) + "\',\'" + \
|
|
|
416 |
str(p1_current_power_in) + "\',\'" + \
|
|
|
417 |
p1_unit_current_power_in + "\',\'" + \
|
|
|
418 |
str(p1_current_power_out) + "\',\'" + \
|
|
|
419 |
p1_unit_current_power_out + "\',\'" + \
|
|
|
420 |
str(p1_current_threshold) + "\',\'" + \
|
|
|
421 |
p1_unit_current_threshold + "\',\'" + \
|
|
|
422 |
str(p1_current_switch_position) + "\',\'" + \
|
|
|
423 |
str(p1_powerfailures) + "\',\'" + \
|
|
|
424 |
str(p1_long_powerfailures) + "\',\'" + \
|
|
|
425 |
p1_long_powerfailures_log + "\',\'" + \
|
|
|
426 |
str(p1_voltage_sags_l1) + "\',\'" + \
|
|
|
427 |
str(p1_voltage_sags_l2) + "\',\'" + \
|
|
|
428 |
str(p1_voltage_sags_l3) + "\',\'" + \
|
|
|
429 |
str(p1_voltage_swells_l1) + "\',\'" + \
|
|
|
430 |
str(p1_voltage_swells_l2) + "\',\'" + \
|
|
|
431 |
str(p1_voltage_swells_l3) + "\',\'" + \
|
|
|
432 |
str(p1_instantaneous_current_l1) + "\',\'" + \
|
|
|
433 |
p1_unit_instantaneous_current_l1 + "\',\'" + \
|
|
|
434 |
str(p1_instantaneous_current_l2) + "\',\'" + \
|
|
|
435 |
p1_unit_instantaneous_current_l2 + "\',\'" + \
|
|
|
436 |
str(p1_instantaneous_current_l3) + "\',\'" + \
|
|
|
437 |
p1_unit_instantaneous_current_l3 + "\',\'" + \
|
|
|
438 |
str(p1_voltage_l1) + "\',\'" + \
|
|
|
439 |
p1_unit_voltage_l1 + "\',\'" + \
|
|
|
440 |
str(p1_voltage_l2) + "\',\'" + \
|
|
|
441 |
p1_unit_voltage_l2 + "\',\'" + \
|
|
|
442 |
str(p1_voltage_l3) + "\',\'" + \
|
|
|
443 |
p1_unit_voltage_l3 + "\',\'" + \
|
|
|
444 |
str(p1_instantaneous_active_power_in_l1) + "\',\'" + \
|
|
|
445 |
p1_unit_instantaneous_active_power_in_l1 + "\',\'" + \
|
|
|
446 |
str(p1_instantaneous_active_power_in_l2) + "\',\'" + \
|
|
|
447 |
p1_unit_instantaneous_active_power_in_l2 + "\',\'" + \
|
|
|
448 |
str(p1_instantaneous_active_power_in_l3) + "\',\'" + \
|
|
|
449 |
p1_unit_instantaneous_active_power_in_l3 + "\',\'" + \
|
|
|
450 |
str(p1_instantaneous_active_power_out_l1) + "\',\'" + \
|
|
|
451 |
p1_unit_instantaneous_active_power_out_l1 + "\',\'" + \
|
|
|
452 |
str(p1_instantaneous_active_power_out_l2) + "\',\'" + \
|
|
|
453 |
p1_unit_instantaneous_active_power_out_l2 + "\',\'" + \
|
|
|
454 |
str(p1_instantaneous_active_power_out_l3) + "\',\'" + \
|
|
|
455 |
p1_unit_instantaneous_active_power_out_l3 + "\',\'" + \
|
|
|
456 |
p1_message_code + "\',\'" + \
|
|
|
457 |
p1_message_text + "\',\'" + \
|
|
|
458 |
str(p1_channel_1.id) + "\',\'" + \
|
|
|
459 |
str(p1_channel_1.type_id) + "\',\'" + \
|
|
|
460 |
p1_channel_1.type_desc + "\',\'" + \
|
|
|
461 |
str(p1_channel_1.equipment_id) + "\',\'" + \
|
|
|
462 |
p1_channel_1.timestamp + "\',\'" + \
|
|
|
463 |
str(p1_channel_1.meterreading) + "\',\'" + \
|
|
|
464 |
p1_channel_1.unit + "\',\'" + \
|
|
|
465 |
str(p1_channel_1.valveposition) + "\',\'" + \
|
|
|
466 |
str(p1_channel_2.id) + "\',\'" + \
|
|
|
467 |
str(p1_channel_2.type_id) + "\',\'" + \
|
|
|
468 |
p1_channel_2.type_desc + "\',\'" + \
|
|
|
469 |
str(p1_channel_2.equipment_id) + "\',\'" + \
|
|
|
470 |
p1_channel_2.timestamp + "\',\'" + \
|
|
|
471 |
str(p1_channel_2.meterreading) + "\',\'" + \
|
|
|
472 |
p1_channel_2.unit + "\',\'" + \
|
|
|
473 |
str(p1_channel_2.valveposition) + "\',\'" + \
|
|
|
474 |
str(p1_channel_3.id) + "\',\'" + \
|
|
|
475 |
str(p1_channel_3.type_id) + "\',\'" + \
|
|
|
476 |
p1_channel_3.type_desc + "\',\'" + \
|
|
|
477 |
str(p1_channel_3.equipment_id) + "\',\'" + \
|
|
|
478 |
p1_channel_3.timestamp + "\',\'" + \
|
|
|
479 |
str(p1_channel_3.meterreading) + "\',\'" + \
|
|
|
480 |
p1_channel_3.unit + "\',\'" + \
|
|
|
481 |
str(p1_channel_3.valveposition) + "\',\'" + \
|
|
|
482 |
str(p1_channel_4.id) + "\',\'" + \
|
|
|
483 |
str(p1_channel_4.type_id) + "\',\'" + \
|
|
|
484 |
p1_channel_4.type_desc + "\',\'" + \
|
|
|
485 |
str(p1_channel_4.equipment_id) + "\',\'" + \
|
|
|
486 |
p1_channel_4.timestamp + "\',\'" + \
|
|
|
487 |
str(p1_channel_4.meterreading) + "\',\'" + \
|
|
|
488 |
p1_channel_4.unit + "\',\'" + \
|
|
|
489 |
str(p1_channel_4.valveposition) + "\')"
|
|
|
490 |
# print(query)
|
|
|
491 |
try:
|
|
|
492 |
db = mysql.connector.connect(user=p1_mysql_user, password=p1_mysql_passwd, host=p1_mysql_host, database=p1_mysql_db)
|
|
|
493 |
c = db.cursor()
|
|
|
494 |
c.execute (query)
|
|
|
495 |
db.commit()
|
|
|
496 |
print ("P2 telegram in database %s / %s gelogd op: %s" % (p1_mysql_host, p1_mysql_db, p1_timestamp) )
|
|
|
497 |
c.close()
|
|
|
498 |
db.close()
|
|
|
499 |
except:
|
|
|
500 |
show_error()
|
|
|
501 |
print ("Fout bij het openen van / schrijven naar database %s / %s." % (p1_mysql_host, p1_mysql_db))
|
|
|
502 |
return
|
|
|
503 |
|
|
|
504 |
def db_p3_telegram():
|
|
|
505 |
query = "insert into p3_log values (\'" + \
|
|
|
506 |
ID + "\',\'" + \
|
|
|
507 |
p1_timestamp + "\',\'" + \
|
|
|
508 |
p1_meter_supplier + "\',\'" + \
|
|
|
509 |
p1_header + "\',\'" + \
|
|
|
510 |
p1_dsmr_version + "\',\'" + \
|
|
|
511 |
p1_equipment_id + "\',\'" + \
|
|
|
512 |
str(p1_meterreading_in_1) + "\',\'" + \
|
|
|
513 |
p1_unitmeterreading_in_1 + "\',\'" + \
|
|
|
514 |
str(p1_meterreading_in_2) + "\',\'" + \
|
|
|
515 |
p1_unitmeterreading_in_2 + "\',\'" + \
|
|
|
516 |
str(p1_meterreading_out_1) + "\',\'" +\
|
|
|
517 |
p1_unitmeterreading_out_1 + "\',\'" + \
|
|
|
518 |
str(p1_meterreading_out_2) + "\',\'" + \
|
|
|
519 |
p1_unitmeterreading_out_2 + "\',\'" + \
|
|
|
520 |
str(p1_current_tariff) + "\',\'" + \
|
|
|
521 |
str(p1_current_power_in) + "\',\'" + \
|
|
|
522 |
p1_unit_current_power_in + "\',\'" + \
|
|
|
523 |
str(p1_current_power_out) + "\',\'" + \
|
|
|
524 |
p1_unit_current_power_out + "\',\'" + \
|
|
|
525 |
str(p1_current_threshold) + "\',\'" + \
|
|
|
526 |
p1_unit_current_threshold + "\',\'" + \
|
|
|
527 |
str(p1_current_switch_position) + "\',\'" + \
|
|
|
528 |
str(p1_powerfailures) + "\',\'" + \
|
|
|
529 |
str(p1_long_powerfailures) + "\',\'" + \
|
|
|
530 |
p1_long_powerfailures_log + "\',\'" + \
|
|
|
531 |
str(p1_voltage_sags_l1) + "\',\'" + \
|
|
|
532 |
str(p1_voltage_sags_l2) + "\',\'" + \
|
|
|
533 |
str(p1_voltage_sags_l3) + "\',\'" + \
|
|
|
534 |
str(p1_voltage_swells_l1) + "\',\'" + \
|
|
|
535 |
str(p1_voltage_swells_l2) + "\',\'" + \
|
|
|
536 |
str(p1_voltage_swells_l3) + "\',\'" + \
|
|
|
537 |
str(p1_instantaneous_current_l1) + "\',\'" + \
|
|
|
538 |
p1_unit_instantaneous_current_l1 + "\',\'" + \
|
|
|
539 |
str(p1_instantaneous_current_l2) + "\',\'" + \
|
|
|
540 |
p1_unit_instantaneous_current_l2 + "\',\'" + \
|
|
|
541 |
str(p1_instantaneous_current_l3) + "\',\'" + \
|
|
|
542 |
p1_unit_instantaneous_current_l3 + "\',\'" + \
|
|
|
543 |
str(p1_voltage_l1) + "\',\'" + \
|
|
|
544 |
p1_unit_voltage_l1 + "\',\'" + \
|
|
|
545 |
str(p1_voltage_l2) + "\',\'" + \
|
|
|
546 |
p1_unit_voltage_l2 + "\',\'" + \
|
|
|
547 |
str(p1_voltage_l3) + "\',\'" + \
|
|
|
548 |
p1_unit_voltage_l3 + "\',\'" + \
|
|
|
549 |
str(p1_instantaneous_active_power_in_l1) + "\',\'" + \
|
|
|
550 |
p1_unit_instantaneous_active_power_in_l1 + "\',\'" + \
|
|
|
551 |
str(p1_instantaneous_active_power_in_l2) + "\',\'" + \
|
|
|
552 |
p1_unit_instantaneous_active_power_in_l2 + "\',\'" + \
|
|
|
553 |
str(p1_instantaneous_active_power_in_l3) + "\',\'" + \
|
|
|
554 |
p1_unit_instantaneous_active_power_in_l3 + "\',\'" + \
|
|
|
555 |
str(p1_instantaneous_active_power_out_l1) + "\',\'" + \
|
|
|
556 |
p1_unit_instantaneous_active_power_out_l1 + "\',\'" + \
|
|
|
557 |
str(p1_instantaneous_active_power_out_l2) + "\',\'" + \
|
|
|
558 |
p1_unit_instantaneous_active_power_out_l2 + "\',\'" + \
|
|
|
559 |
str(p1_instantaneous_active_power_out_l3) + "\',\'" + \
|
|
|
560 |
p1_unit_instantaneous_active_power_out_l3 + "\',\'" + \
|
|
|
561 |
p1_message_code + "\',\'" + \
|
|
|
562 |
p1_message_text + "\',\'" + \
|
|
|
563 |
str(p1_channel_1.id) + "\',\'" + \
|
|
|
564 |
str(p1_channel_1.type_id) + "\',\'" + \
|
|
|
565 |
p1_channel_1.type_desc + "\',\'" + \
|
|
|
566 |
str(p1_channel_1.equipment_id) + "\',\'" + \
|
|
|
567 |
p1_channel_1.timestamp + "\',\'" + \
|
|
|
568 |
str(p1_channel_1.meterreading) + "\',\'" + \
|
|
|
569 |
p1_channel_1.unit + "\',\'" + \
|
|
|
570 |
str(p1_channel_1.valveposition) + "\',\'" + \
|
|
|
571 |
str(p1_channel_2.id) + "\',\'" + \
|
|
|
572 |
str(p1_channel_2.type_id) + "\',\'" + \
|
|
|
573 |
p1_channel_2.type_desc + "\',\'" + \
|
|
|
574 |
str(p1_channel_2.equipment_id) + "\',\'" + \
|
|
|
575 |
p1_channel_2.timestamp + "\',\'" + \
|
|
|
576 |
str(p1_channel_2.meterreading) + "\',\'" + \
|
|
|
577 |
p1_channel_2.unit + "\',\'" + \
|
|
|
578 |
str(p1_channel_2.valveposition) + "\',\'" + \
|
|
|
579 |
str(p1_channel_3.id) + "\',\'" + \
|
|
|
580 |
str(p1_channel_3.type_id) + "\',\'" + \
|
|
|
581 |
p1_channel_3.type_desc + "\',\'" + \
|
|
|
582 |
str(p1_channel_3.equipment_id) + "\',\'" + \
|
|
|
583 |
p1_channel_3.timestamp + "\',\'" + \
|
|
|
584 |
str(p1_channel_3.meterreading) + "\',\'" + \
|
|
|
585 |
p1_channel_3.unit + "\',\'" + \
|
|
|
586 |
str(p1_channel_3.valveposition) + "\',\'" + \
|
|
|
587 |
str(p1_channel_4.id) + "\',\'" + \
|
|
|
588 |
str(p1_channel_4.type_id) + "\',\'" + \
|
|
|
589 |
p1_channel_4.type_desc + "\',\'" + \
|
|
|
590 |
str(p1_channel_4.equipment_id) + "\',\'" + \
|
|
|
591 |
p1_channel_4.timestamp + "\',\'" + \
|
|
|
592 |
str(p1_channel_4.meterreading) + "\',\'" + \
|
|
|
593 |
p1_channel_4.unit + "\',\'" + \
|
|
|
594 |
str(p1_channel_4.valveposition) + "\')"
|
|
|
595 |
# print(query)
|
|
|
596 |
try:
|
|
|
597 |
db = mysql.connector.connect(user=p1_mysql_user, password=p1_mysql_passwd, host=p1_mysql_host, database=p1_mysql_db)
|
|
|
598 |
c = db.cursor()
|
|
|
599 |
c.execute (query)
|
|
|
600 |
db.commit()
|
|
|
601 |
print ("P3 telegram in database %s / %s gelogd op: %s" % (p1_mysql_host, p1_mysql_db, p1_timestamp) )
|
|
|
602 |
c.close()
|
|
|
603 |
db.close()
|
|
|
604 |
except:
|
|
|
605 |
show_error()
|
|
|
606 |
print ("Fout bij het openen van / schrijven naar database %s / %s." % (p1_mysql_host, p1_mysql_db))
|
|
|
607 |
return
|
|
|
608 |
|
|
|
609 |
######################
|
|
|
610 |
#PVOutput.org output #
|
|
|
611 |
######################
|
|
|
612 |
def pvo_p1_telegram():
|
|
|
613 |
global pvo_prev_date
|
|
|
614 |
global p1_prev_meterreading_out_1, p1_prev_meterreading_out_2
|
|
|
615 |
global p1_prev_meterreading_in_1, p1_prev_meterreading_in_2
|
|
|
616 |
if pvo_url[0:7] != "http://":
|
|
|
617 |
print("Invalid PVOutput.org URL to post to, must be of form http://host/service: %s" % pvo_url)
|
|
|
618 |
sys.exit(1)
|
|
|
619 |
url = pvo_url[7:].split('/')
|
|
|
620 |
pvo_host = url[0]
|
|
|
621 |
pvo_service = '/' + '/'.join(url[1:])
|
|
|
622 |
#
|
|
|
623 |
# d Date
|
|
|
624 |
# t Time
|
|
|
625 |
# v1 energy generation (Wh) => P1 Export
|
|
|
626 |
# v2 power generation (W) => P1 Export
|
|
|
627 |
# v3 energy consumption (Wh) => P1 Import
|
|
|
628 |
# v4 power consumption (W) => P1 Import
|
|
|
629 |
# v5 temperature (c)
|
|
|
630 |
# v6 voltage (V)
|
|
|
631 |
# c1 cumulative flag: if set to '1' lifetime values are to be passed
|
|
|
632 |
# n net flag: if set to '1' net import/export values are to be passed
|
|
|
633 |
#
|
|
|
634 |
pvo_date=str(datetime.datetime.strftime(datetime.datetime.strptime(p1_timestamp, "%Y-%m-%d %H:%M:%S" ), "%Y%m%d" ))
|
|
|
635 |
pvo_time=str(datetime.datetime.strftime(datetime.datetime.strptime(p1_timestamp, "%Y-%m-%d %H:%M:%S" ), "%H:%M" ))
|
|
|
636 |
|
|
|
637 |
# Initialize pvo volumes when a new day has started
|
|
|
638 |
if pvo_prev_date != pvo_date:
|
|
|
639 |
print ("PVOutput volumes worden gereset, vorige datum: %s, huidige datum: %s" % (pvo_prev_date, pvo_date) )
|
|
|
640 |
p1_prev_meterreading_out_1 = p1_meterreading_out_1
|
|
|
641 |
p1_prev_meterreading_out_2 = p1_meterreading_out_2
|
|
|
642 |
p1_prev_meterreading_in_1 = p1_meterreading_in_1
|
|
|
643 |
p1_prev_meterreading_in_2 = p1_meterreading_in_2
|
|
|
644 |
pvo_prev_date = pvo_date
|
|
|
645 |
|
|
|
646 |
pvo_volume_out=round((p1_meterreading_out_1+p1_meterreading_out_2-p1_prev_meterreading_out_1-p1_prev_meterreading_out_2) * 1000)
|
|
|
647 |
pvo_volume_in=round((p1_meterreading_in_1+p1_meterreading_in_2-p1_prev_meterreading_in_1-p1_prev_meterreading_in_2) *1000)
|
|
|
648 |
|
|
|
649 |
pvo_power_out=round(p1_current_power_out * 1000)
|
|
|
650 |
pvo_power_in=round(p1_current_power_in * 1000)
|
|
|
651 |
|
|
|
652 |
print("PVOutput volume out (v1): %s"% pvo_volume_out)
|
|
|
653 |
print("MR1 out: %s"% p1_meterreading_out_1)
|
|
|
654 |
print("MR2 out: %s"% p1_meterreading_out_2)
|
|
|
655 |
print("Prev MR1 out: %s"% p1_prev_meterreading_out_1)
|
|
|
656 |
print("Prev MR2 out: %s"% p1_prev_meterreading_out_2)
|
|
|
657 |
|
|
|
658 |
print("PVOutput volume in (v3): %s"% pvo_volume_in)
|
|
|
659 |
print("MR1 in: %s"% p1_meterreading_in_1)
|
|
|
660 |
print("MR2 in: %s"% p1_meterreading_in_2)
|
|
|
661 |
print("Prev MR1 in: %s"% p1_prev_meterreading_in_1)
|
|
|
662 |
print("Prev MR2 in: %s"% p1_prev_meterreading_in_2)
|
|
|
663 |
|
|
|
664 |
|
|
|
665 |
pvo_cumulative = 0 # volumes are reset once a day
|
|
|
666 |
pvo_net = 0 #Typically not correct but the best you can get with this PVOutput interface as net=1 discards the volume data
|
|
|
667 |
params = urllib.parse.urlencode({ 'd' : pvo_date,
|
|
|
668 |
't' : pvo_time,
|
|
|
669 |
# This is how it should be
|
|
|
670 |
# 'v1' : pvo_volume_out,
|
|
|
671 |
# 'v2' : pvo_power_out,
|
|
|
672 |
# 'v3' : pvo_volume_in,
|
|
|
673 |
# 'v4' : pvo_power_in,
|
|
|
674 |
# Patch wrong behaviour of PVOutput in case of using net values because PVOutput obly uses power values in this case
|
|
|
675 |
'v1' : pvo_volume_out,
|
|
|
676 |
'v2' : pvo_power_out,
|
|
|
677 |
'v3' : pvo_volume_in,
|
|
|
678 |
'v4' : pvo_power_in,
|
|
|
679 |
'c1' : pvo_cumulative,
|
|
|
680 |
'n' : pvo_net })
|
|
|
681 |
headers = {"Content-type": "application/x-www-form-urlencoded",
|
|
|
682 |
"Accept": "text/plain",
|
|
|
683 |
"X-Pvoutput-SystemId" : pvo_systemid,
|
|
|
684 |
"X-Pvoutput-Apikey" : pvo_apikey}
|
|
|
685 |
print("Verbinden met %s" % pvo_host)
|
|
|
686 |
try:
|
|
|
687 |
conn = http.client.HTTPConnection(pvo_host)
|
|
|
688 |
# print("Sending data: %s" % params)
|
|
|
689 |
try:
|
|
|
690 |
conn.request("POST", pvo_service, params, headers)
|
|
|
691 |
response = conn.getresponse()
|
|
|
692 |
if response.status != 200:
|
|
|
693 |
print ("Fout bij het schrijven naar %s / %s. Response: %s %s %s" % (pvo_host, pvo_systemid, response.status, response.reason, response.read()))
|
|
|
694 |
else:
|
|
|
695 |
print ("Delta P1 telegram in %s / %s gelogd op: %s. Response: %s %s" % (pvo_host, pvo_systemid, p1_timestamp,response.status, response.reason) )
|
|
|
696 |
except:
|
|
|
697 |
show_error()
|
|
|
698 |
print ("Fout bij het schrijven naar %s / %s." % (pvo_host, pvo_systemid))
|
|
|
699 |
except:
|
|
|
700 |
show_error()
|
|
|
701 |
print ("Fout bij het verbinden met %s / %s." % (pvo_host, pvo_systemid))
|
|
|
702 |
|
|
|
703 |
#################################################################
|
|
|
704 |
# Start of procedures to add other metering data to p1_telegram #
|
|
|
705 |
#################################################################
|
|
|
706 |
|
|
|
707 |
#################################################################
|
|
|
708 |
# PV Inverter Data #
|
|
|
709 |
#################################################################
|
|
|
710 |
def get_pv_data(channelA,p1_channelA,channelB,p1_channelB):
|
|
|
711 |
query = "select pv_timestamp, pv_equipmentmodel, pv_equipmentid, pv_cumvolume, pv_cumvolumeunit, pv_intvolume, pv_intvolumeunit, pv_power, pv_powerunit from pv_log order by pv_timestamp desc"
|
|
|
712 |
# print(query)
|
|
|
713 |
try:
|
|
|
714 |
db = mysql.connector.connect(user=p1_mysql_user, password=p1_mysql_passwd, host=p1_mysql_host, database=p1_mysql_db)
|
|
|
715 |
c = db.cursor()
|
|
|
716 |
c.execute(query)
|
|
|
717 |
pv_timestamp, pv_equipmentmodel, pv_equipmentid, pv_cumvolume, pv_cumvolumeunit, pv_intvolume, pv_intvolumeunit, pv_power, pv_powerunit = c.fetchone()
|
|
|
718 |
p1_channelA.id = channelA
|
|
|
719 |
p1_channelA.type_id = 1
|
|
|
720 |
p1_channelA.type_desc = "E-Production volume"
|
|
|
721 |
p1_channelA.equipment_id = pv_equipmentid
|
|
|
722 |
p1_channelA.timestamp = str(datetime.datetime.strftime(pv_timestamp, "%Y-%m-%d %H:%M:%S" ))
|
|
|
723 |
p1_channelA.meterreading = pv_cumvolume
|
|
|
724 |
p1_channelA.unit = pv_cumvolumeunit
|
|
|
725 |
p1_channelA.valveposition = 1
|
|
|
726 |
print ("PV volume %s toegevoegd aan P1 telegram - kanaal %s" % (pv_timestamp, channelA ) )
|
|
|
727 |
if channelB != 0:
|
|
|
728 |
p1_channelB.id = channelB
|
|
|
729 |
p1_channelB.type_id = 1
|
|
|
730 |
p1_channelB.type_desc = "E-Production power"
|
|
|
731 |
p1_channelB.equipment_id = pv_equipmentid
|
|
|
732 |
p1_channelB.timestamp = str(datetime.datetime.strftime(pv_timestamp, "%Y-%m-%d %H:%M:%S" ))
|
|
|
733 |
p1_channelB.meterreading = pv_power
|
|
|
734 |
p1_channelB.unit = pv_powerunit
|
|
|
735 |
p1_channelB.valveposition = 1
|
|
|
736 |
print ("PV vermogen %s toegevoegd aan P1 telegram - kanaal %s" % (pv_timestamp, channelB ) )
|
|
|
737 |
#c.close()
|
|
|
738 |
db.close()
|
|
|
739 |
except:
|
|
|
740 |
show_error()
|
|
|
741 |
print ("Fout bij het openen / lezen van database %s / %s. PV telegram niet opgehaald." % (p1_mysql_host, p1_mysql_db))
|
|
|
742 |
|
|
|
743 |
return
|
|
|
744 |
#################################################################
|
|
|
745 |
# Heat Data #
|
|
|
746 |
#################################################################
|
|
|
747 |
def get_heat_data(channelA,p1_channelA,channelB,p1_channelB):
|
|
|
748 |
query = "select heat_timestamp, heat_equipment_id, heat_meterreading_energy, heat_unitmeterreading_energy, heat_meterreading_volume, heat_unitmeterreading_volume from heat_log order by heat_timestamp desc"
|
|
|
749 |
# print(query)
|
|
|
750 |
try:
|
|
|
751 |
db = mysql.connector.connect(user=p1_mysql_user, password=p1_mysql_passwd, host=p1_mysql_host, database=p1_mysql_db)
|
|
|
752 |
c = db.cursor()
|
|
|
753 |
c.execute(query)
|
|
|
754 |
heat_timestamp, heat_equipment_id, heat_meterreading_energy, heat_unitmeterreading_energy, heat_meterreading_volume, heat_unitmeterreading_volume = c.fetchone()
|
|
|
755 |
p1_channelA.id = channelA
|
|
|
756 |
p1_channelA.type_id = 5
|
|
|
757 |
p1_channelA.type_desc = "Heat energy"
|
|
|
758 |
p1_channelA.equipment_id = heat_equipment_id
|
|
|
759 |
p1_channelA.timestamp = str(datetime.datetime.strftime(heat_timestamp, "%Y-%m-%d %H:%M:%S" ))
|
|
|
760 |
p1_channelA.meterreading = heat_meterreading_energy
|
|
|
761 |
p1_channelA.unit = heat_unitmeterreading_energy
|
|
|
762 |
p1_channelA.valveposition = 1
|
|
|
763 |
print ("Warmte energie %s toegevoegd aan P1 telegram - kanaal %s" % (heat_timestamp, channelA ) )
|
|
|
764 |
if channelB != 0:
|
|
|
765 |
p1_channelB.id = channelB
|
|
|
766 |
p1_channelB.type_id = 5
|
|
|
767 |
p1_channelB.type_desc = "Heat flow"
|
|
|
768 |
p1_channelB.equipment_id = heat_equipment_id
|
|
|
769 |
p1_channelB.timestamp = str(datetime.datetime.strftime(heat_timestamp, "%Y-%m-%d %H:%M:%S" ))
|
|
|
770 |
p1_channelB.meterreading = heat_meterreading_volume
|
|
|
771 |
p1_channelB.unit = heat_unitmeterreading_volume
|
|
|
772 |
p1_channelB.valveposition = 1
|
|
|
773 |
print ("Warmte flow %s toegevoegd aan P1 telegram - kanaal %s" % (heat_timestamp, channelB ) )
|
|
|
774 |
#c.close()
|
|
|
775 |
db.close()
|
|
|
776 |
except:
|
|
|
777 |
show_error()
|
|
|
778 |
print ("Fout bij het openen / lezen van database %s / %s. Heat telegram niet opgehaald." % (p1_mysql_host, p1_mysql_db))
|
|
|
779 |
return
|
|
|
780 |
#################################################################
|
|
|
781 |
# S0 Pulse Counter Data #
|
|
|
782 |
#################################################################
|
|
|
783 |
def get_s0_data(id,meter,channel,p1_channel,type_id,type_desc):
|
|
|
784 |
# Use the total s0 volume to improve performance. In the S0 Datalogger, make sure it is not reset!!
|
|
|
785 |
query = "select s0_timestamp, s0_id, s0_m" + meter + "_volume_total, s0_m" + meter + "_volume_total_unit from s0_log where s0_id = '" + id + "' order by s0_timestamp desc limit 1"
|
|
|
786 |
# print(query)
|
|
|
787 |
try:
|
|
|
788 |
db = mysql.connector.connect(user=p1_mysql_user, password=p1_mysql_passwd, host=p1_mysql_host, database=p1_mysql_db)
|
|
|
789 |
c = db.cursor()
|
|
|
790 |
c.execute(query)
|
|
|
791 |
s0_timestamp, s0_id, s0_volume_total, s0_volume_total_unit = c.fetchone()
|
|
|
792 |
p1_channel.id = channel
|
|
|
793 |
p1_channel.type_id = type_id
|
|
|
794 |
p1_channel.type_desc = type_desc
|
|
|
795 |
p1_channel.equipment_id = s0_id + "-" + meter
|
|
|
796 |
p1_channel.timestamp = str(datetime.datetime.strftime(s0_timestamp, "%Y-%m-%d %H:%M:%S" ))
|
|
|
797 |
p1_channel.meterreading = s0_volume_total
|
|
|
798 |
p1_channel.unit = s0_volume_total_unit
|
|
|
799 |
p1_channel.valveposition = "1"
|
|
|
800 |
print ("S0 %s %s toegevoegd aan P1 telegram - kanaal %s" % (type_desc, s0_timestamp,channel))
|
|
|
801 |
#c.close()
|
|
|
802 |
db.close()
|
|
|
803 |
except:
|
|
|
804 |
show_error()
|
|
|
805 |
print ("Fout bij het openen / lezen van database %s / %s. S0 telegram niet opgehaald." % (p1_mysql_host, p1_mysql_db))
|
|
|
806 |
return
|
|
|
807 |
#################################################################
|
|
|
808 |
# Electricity sub-meter #
|
|
|
809 |
#################################################################
|
|
|
810 |
def get_power_data(channel,p1_channel,type_id,type_desc):
|
|
|
811 |
query = "select power_timestamp, power_equipment_id, power_meterreading_1_tot, power_unitmeterreading_1_tot from power_log order by power_timestamp desc"
|
|
|
812 |
# print(query)
|
|
|
813 |
try:
|
|
|
814 |
db = mysql.connector.connect(user=p1_mysql_user, password=p1_mysql_passwd, host=p1_mysql_host, database=p1_mysql_db)
|
|
|
815 |
c = db.cursor()
|
|
|
816 |
c.execute(query)
|
|
|
817 |
power_timestamp, power_equipment_id, power_meterreading_1_tot, power_unitmeterreading_1_tot = c.fetchone()
|
|
|
818 |
p1_channel.id = channel
|
|
|
819 |
p1_channel.type_id = type_id
|
|
|
820 |
p1_channel.type_desc = type_desc
|
|
|
821 |
p1_channel.equipment_id = row.power_equipment_id
|
|
|
822 |
p1_channel.timestamp = str(row.power_timestamp)
|
|
|
823 |
p1_channel.meterreading = power_meterreading_1_tot
|
|
|
824 |
p1_channel.unit = power_unitmeterreading_1_tot
|
|
|
825 |
p1_channel.valveposition = "1"
|
|
|
826 |
print ("Elektra %s %s toegevoegd aan P1 telegram - kanaal %s" % (type_desc, power_timestamp,channel) )
|
|
|
827 |
#c.close()
|
|
|
828 |
db.close()
|
|
|
829 |
except:
|
|
|
830 |
show_error()
|
|
|
831 |
print ("Fout bij het openen / lezen van database %s / %s. Iskra telegram niet opgehaald." % (p1_mysql_host, p1_mysql_db))
|
|
|
832 |
|
|
|
833 |
return
|
|
|
834 |
#################################################################
|
|
|
835 |
# End of procedures to add other metering data to p1_telegram #
|
|
|
836 |
#################################################################
|
|
|
837 |
|
|
|
838 |
################################################################################################################################################
|
|
|
839 |
#Main program
|
|
|
840 |
################################################################################################################################################
|
|
|
841 |
print("%s %s" % (progname, version))
|
|
|
842 |
comport=-1
|
|
|
843 |
win_os = (os.name == 'nt')
|
|
|
844 |
if win_os:
|
|
|
845 |
print("Windows Mode")
|
|
|
846 |
else:
|
|
|
847 |
print("Non-Windows Mode")
|
|
|
848 |
print("Python version %s.%s.%s" % sys.version_info[:3])
|
|
|
849 |
print ("Control-C to abort")
|
|
|
850 |
|
|
|
851 |
################################################################################################################################################
|
|
|
852 |
#Commandline arguments parsing
|
|
|
853 |
################################################################################################################################################
|
|
|
854 |
parser = argparse.ArgumentParser(prog=progname, description='P1 Datalogger - www.smartmeterdashboard.nl', epilog="Copyright (c) 2011/2012/2013/2014 J. van der Linde. Although there is a explicit copyright on this sourcecode, anyone may use it freely under a 'Creative Commons Naamsvermelding-NietCommercieel-GeenAfgeleideWerken 3.0 Nederland' license.")
|
|
|
855 |
#parser.add_argument("-c", "--comport", help="COM-port identifier", type=int)
|
|
|
856 |
#parser.add_argument("-l", "--loginterval", help="Log frequency in 10 second-units, default=1", default=1, type=int)
|
|
|
857 |
#parser.add_argument("-o", "--output", help="Output mode, default='screen'", default='screen', choices=['screen', 'csv', 'db'])
|
|
|
858 |
#parser.add_argument("-pvo", "--pvoutput", help="Output to PVOutput ==EXPERIMENTAL==, default='N'", default='N', choices=['Y', 'N'])
|
|
|
859 |
#parser.add_argument("-pvoapi", "--pvoutputapikey", help="PVOutput.org API key")
|
|
|
860 |
#parser.add_argument("-pvosys", "--pvoutputsystemid", help="PVOutput.org system id", type=int)
|
|
|
861 |
#parser.add_argument("-s", "--server", help="Database server, default='localhost'", default='localhost')
|
|
|
862 |
#parser.add_argument("-u", "--user", help="Database user, default='root'", default='root')
|
|
|
863 |
#parser.add_argument("-p", "--password", help="Database user password, default='password'", default='password')
|
|
|
864 |
#parser.add_argument("-d", "--database", help="Database name, default=p1'", default='p1')
|
|
|
865 |
parser.add_argument("-v", "--version", help="DSMR COM-port setting version, default=3'", choices=['2','3','4'], default='3')
|
|
|
866 |
args = parser.parse_args()
|
|
|
867 |
|
|
|
868 |
################################################################
|
|
|
869 |
# Script arguments parsing
|
|
|
870 |
mydir = os.path.dirname(os.path.abspath(__file__))
|
|
|
871 |
config = configparser.RawConfigParser()
|
|
|
872 |
#config.read([mydir + 'P1.cfg'])
|
|
|
873 |
config.read(['/usr/local/P1.cfg'])
|
|
|
874 |
|
|
|
875 |
cfgloginterval = config.getint('cfgGeneral', 'loginterval')
|
|
|
876 |
cfgoutput = config.get('cfgGeneral', 'output')
|
|
|
877 |
|
|
|
878 |
cfgserver = config.get('cfgDatabase', 'server')
|
|
|
879 |
cfguser = config.get('cfgDatabase', 'user')
|
|
|
880 |
cfgpassword = config.get('cfgDatabase', 'password')
|
|
|
881 |
cfgdatabase = config.get('cfgDatabase', 'database')
|
|
|
882 |
cfgtable = config.get('cfgDatabase', 'table')
|
|
|
883 |
cfgtable2 = config.get('cfgDatabase', 'table2')
|
|
|
884 |
cfgtable3 = config.get('cfgDatabase', 'table3')
|
|
|
885 |
|
|
|
886 |
cfgcomport = config.get('cfgCOM', 'comport')
|
|
|
887 |
cfgtcphost = config.get('cfgNET', 'tcphost')
|
|
|
888 |
cfgtcpport = config.getint('cfgNET', 'tcpport')
|
|
|
889 |
|
|
|
890 |
cfgpvo = config.get('cfgPVO', 'pvo')
|
|
|
891 |
cfgpvoapi = config.get('cfgPVO', 'pvoapi')
|
|
|
892 |
cfgpvosys = config.getint('cfgPVO', 'pvosys')
|
|
|
893 |
# End parsing
|
|
|
894 |
################################################################
|
|
|
895 |
|
|
|
896 |
if cfgcomport == None:
|
|
|
897 |
parser.print_help()
|
|
|
898 |
print ("\r")
|
|
|
899 |
print("%s: error: The following arguments are required: -c/--comport." % progname)
|
|
|
900 |
print("Allowed values for argument -c/--comport:")
|
|
|
901 |
#scanserial returns win_os serial ports and non win_os USB serial ports
|
|
|
902 |
for n,s in scan_serial():
|
|
|
903 |
port=n+1
|
|
|
904 |
print ("%d --> %s" % (port,s) )
|
|
|
905 |
print ("Program aborted.")
|
|
|
906 |
sys.exit()
|
|
|
907 |
|
|
|
908 |
comport = int(cfgcomport)
|
|
|
909 |
pvo_output = (cfgpvo == "Y")
|
|
|
910 |
log_interval = cfgloginterval
|
|
|
911 |
if pvo_output and (cfgpvoapi == None or cfgpvosys == None):
|
|
|
912 |
parser.print_help()
|
|
|
913 |
print ("\r")
|
|
|
914 |
print("%s: error: If -pvo/--pvoutput is 'Y', the following arguments are required: -pvoapi/--pvoutputapikey and -pvosys/--pvoutputsystemid." % progname)
|
|
|
915 |
print ("Program aborted.")
|
|
|
916 |
sys.exit()
|
|
|
917 |
|
|
|
918 |
if pvo_output and log_interval < 6:
|
|
|
919 |
log_interval = 6
|
|
|
920 |
print("%s: warning: If -pvo/--pvoutput is 'Y', log interval should be 6 or higher. Log interval 6 used instead." % progname)
|
|
|
921 |
output_mode = cfgoutput
|
|
|
922 |
dsmr_version = args.version
|
|
|
923 |
pvo_apikey = cfgpvoapi
|
|
|
924 |
pvo_systemid = cfgpvosys
|
|
|
925 |
pvo_prev_date = ""
|
|
|
926 |
|
|
|
927 |
#Show startup arguments
|
|
|
928 |
print ("\r")
|
|
|
929 |
print ("Startup parameters:")
|
|
|
930 |
print ("Output mode : %s" % output_mode)
|
|
|
931 |
print ("PVOutput.org logging : %s" % pvo_output)
|
|
|
932 |
if pvo_output:
|
|
|
933 |
print ("PVOutput.org API key : %s" % pvo_apikey)
|
|
|
934 |
print ("PVOutput.org system ID: %s" % pvo_systemid)
|
|
|
935 |
print ("Log interval : %s (once every %s seconds)" % (log_interval, log_interval * 10))
|
|
|
936 |
print ("DSMR COM-port setting : %s" % dsmr_version)
|
|
|
937 |
if (output_mode == "db" or import_db) and MySQL_loaded:
|
|
|
938 |
p1_mysql_host=cfgserver
|
|
|
939 |
p1_mysql_user=cfguser
|
|
|
940 |
p1_mysql_passwd=cfgpassword
|
|
|
941 |
p1_mysql_db=cfgdatabase
|
|
|
942 |
print ("Database credentials used:")
|
|
|
943 |
print ("- Server : %s" % p1_mysql_host)
|
|
|
944 |
print ("- User : %s" % p1_mysql_user)
|
|
|
945 |
print ("- Password: %s" % p1_mysql_passwd)
|
|
|
946 |
print ("- Database: %s" % p1_mysql_db)
|
|
|
947 |
if (output_mode == "db" or import_db) and not MySQL_loaded:
|
|
|
948 |
print("%s: warning: MySQL Connector/Python not found. Output mode 'db' not allowed. Output mode 'csv' used instead." % progname)
|
|
|
949 |
output_mode = "csv"
|
|
|
950 |
import_db = False
|
|
|
951 |
#################################################################################################################################################
|
|
|
952 |
|
|
|
953 |
#Set COM port config
|
|
|
954 |
if comport != 0:
|
|
|
955 |
ser = serial.Serial()
|
|
|
956 |
if dsmr_version == '2' or dsmr_version == '3':
|
|
|
957 |
ser.baudrate = 9600
|
|
|
958 |
ser.bytesize=serial.SEVENBITS
|
|
|
959 |
ser.parity=serial.PARITY_EVEN
|
|
|
960 |
ser.stopbits=serial.STOPBITS_ONE
|
|
|
961 |
ser.xonxoff=1
|
|
|
962 |
if dsmr_version == '4':
|
|
|
963 |
ser.baudrate = 115200
|
|
|
964 |
ser.bytesize=serial.EIGHTBITS
|
|
|
965 |
ser.parity=serial.PARITY_NONE
|
|
|
966 |
ser.stopbits=serial.STOPBITS_ONE
|
|
|
967 |
ser.xonxoff=1
|
|
|
968 |
ser.rtscts=0
|
|
|
969 |
ser.timeout=20
|
|
|
970 |
if win_os:
|
|
|
971 |
ser.port=comport-1
|
|
|
972 |
print ("COM-port : %d (%s)" % (comport, ser.name) )
|
|
|
973 |
else:
|
|
|
974 |
ser.port="/dev/ttyUSB"+str(comport-1)
|
|
|
975 |
port="/dev/ttyUSB"+str(comport-1) # Linux Style for /dev/ttyUSB0, /dev/ttyUSB1, etc...
|
|
|
976 |
print ("COM-port : %d (%s)" % (comport, port) )
|
|
|
977 |
else:
|
|
|
978 |
print ("Inputfile assigned : 'p1test.log'")
|
|
|
979 |
|
|
|
980 |
#Open COM port
|
|
|
981 |
if comport != 0:
|
|
|
982 |
try:
|
|
|
983 |
ser.open()
|
|
|
984 |
except:
|
|
|
985 |
if win_os:
|
|
|
986 |
sys.exit ("Error opening %s. Program aborted." % ser.name)
|
|
|
987 |
else:
|
|
|
988 |
sys.exit ("Error opening %s. Program aborted." % port)
|
|
|
989 |
else:
|
|
|
990 |
try:
|
|
|
991 |
ser = open("p1test.log", "rt")
|
|
|
992 |
except:
|
|
|
993 |
sys.exit ("Error opening 'p1test.log'. Program aborted.")
|
|
|
994 |
|
|
|
995 |
|
|
|
996 |
#Initialize
|
|
|
997 |
p1_telegram=False
|
|
|
998 |
p1_meter_supplier=""
|
|
|
999 |
p1_timestamp=""
|
|
|
1000 |
p1_dsmr_version="30"
|
|
|
1001 |
p1_current_threshold=0
|
|
|
1002 |
p1_unit_current_threshold=""
|
|
|
1003 |
p1_current_switch_position=1
|
|
|
1004 |
p1_powerfailures=0
|
|
|
1005 |
p1_long_powerfailures=0
|
|
|
1006 |
p1_long_powerfailures_log=""
|
|
|
1007 |
p1_voltage_sags_l1=0
|
|
|
1008 |
p1_voltage_sags_l2=0
|
|
|
1009 |
p1_voltage_sags_l3=0
|
|
|
1010 |
p1_voltage_swells_l1=0
|
|
|
1011 |
p1_voltage_swells_l2=0
|
|
|
1012 |
p1_voltage_swells_l3=0
|
|
|
1013 |
p1_instantaneous_current_l1=0
|
|
|
1014 |
p1_unit_instantaneous_current_l1=""
|
|
|
1015 |
p1_instantaneous_current_l2=0
|
|
|
1016 |
p1_unit_instantaneous_current_l2=""
|
|
|
1017 |
p1_instantaneous_current_l3=0
|
|
|
1018 |
p1_unit_instantaneous_current_l3=""
|
|
|
1019 |
p1_instantaneous_active_power_in_l1=0
|
|
|
1020 |
p1_unit_instantaneous_active_power_in_l1=""
|
|
|
1021 |
p1_instantaneous_active_power_in_l2=0
|
|
|
1022 |
p1_unit_instantaneous_active_power_in_l2=""
|
|
|
1023 |
p1_instantaneous_active_power_in_l3=0
|
|
|
1024 |
p1_unit_instantaneous_active_power_in_l3=""
|
|
|
1025 |
p1_instantaneous_active_power_out_l1=0
|
|
|
1026 |
p1_unit_instantaneous_active_power_out_l1=""
|
|
|
1027 |
p1_instantaneous_active_power_out_l2=0
|
|
|
1028 |
p1_unit_instantaneous_active_power_out_l2=""
|
|
|
1029 |
p1_instantaneous_active_power_out_l3=0
|
|
|
1030 |
p1_unit_instantaneous_active_power_out_l3=""
|
|
|
1031 |
p1_voltage_l1=0
|
|
|
1032 |
p1_unit_voltage_l1=""
|
|
|
1033 |
p1_voltage_l2=0
|
|
|
1034 |
p1_unit_voltage_l2=""
|
|
|
1035 |
p1_voltage_l3=0
|
|
|
1036 |
p1_unit_voltage_l3=""
|
|
|
1037 |
p1_prev_meterreading_out_1 = 0
|
|
|
1038 |
p1_prev_meterreading_out_2 = 0
|
|
|
1039 |
p1_prev_meterreading_in_1 = 0
|
|
|
1040 |
p1_prev_meterreading_in_2 = 0
|
|
|
1041 |
pvo_volume_initialize = False
|
|
|
1042 |
pvo_prev_date=""
|
|
|
1043 |
|
|
|
1044 |
p1_teller=0
|
|
|
1045 |
|
|
|
1046 |
while 1:
|
|
|
1047 |
p1_line=''
|
|
|
1048 |
#Read 1 line
|
|
|
1049 |
try:
|
|
|
1050 |
p1_raw = ser.readline()
|
|
|
1051 |
except:
|
|
|
1052 |
if comport != 0:
|
|
|
1053 |
if win_os:
|
|
|
1054 |
sys.exit ("Error reading %s. Program aborted." % ser.name)
|
|
|
1055 |
else:
|
|
|
1056 |
sys.exit ("Error reading %s. Program aborted." % port)
|
|
|
1057 |
ser.close()
|
|
|
1058 |
else:
|
|
|
1059 |
sys.exit ("Error reading 'p1test.log'. Program aborted.")
|
|
|
1060 |
ser.close()
|
|
|
1061 |
if comport == 0 and len(p1_raw) == 0:
|
|
|
1062 |
ser.close()
|
|
|
1063 |
sys.exit ("Finished reading 'p1test.log'. Program ended.")
|
|
|
1064 |
p1_str=p1_raw
|
|
|
1065 |
if comport != 0:
|
|
|
1066 |
p1_str=str(p1_raw, "utf-8")
|
|
|
1067 |
p1_line=p1_str.strip()
|
|
|
1068 |
|
|
|
1069 |
#Inspect 1st character
|
|
|
1070 |
if p1_line[0:1] == "/":
|
|
|
1071 |
#Start of new P1 telegram
|
|
|
1072 |
p1_telegram=True
|
|
|
1073 |
p1_teller=p1_teller+1
|
|
|
1074 |
#P1 Timestamp to cover DSMR 3 and before
|
|
|
1075 |
p1_timestamp=datetime.datetime.strftime(datetime.datetime.today(), "%Y-%m-%d %H:%M:%S" )
|
|
|
1076 |
#Initialize P1 channeldata
|
|
|
1077 |
p1_channel_1=P1_ChannelData()
|
|
|
1078 |
p1_channel_2=P1_ChannelData()
|
|
|
1079 |
p1_channel_3=P1_ChannelData()
|
|
|
1080 |
p1_channel_4=P1_ChannelData()
|
|
|
1081 |
|
|
|
1082 |
#Only proceed if P1 telegram start is recognized.
|
|
|
1083 |
if p1_telegram:
|
|
|
1084 |
if p1_line[0:1] == "/":
|
|
|
1085 |
#Header information
|
|
|
1086 |
#eg. /KMP5 KA6U001511209910 (Kamstrup Enexis)
|
|
|
1087 |
#eg. /ISk5\2ME382-1003 (InkraEmeco Liander)
|
|
|
1088 |
#eg. /XMX5XMXABCE000018914 (Landis&Gyr Stedin, Xemex communicatiemodule)
|
|
|
1089 |
#eg. /KFM5KAIFA-METER (Kaifa)
|
|
|
1090 |
p1_meter_supplier=p1_line[1:4]
|
|
|
1091 |
p1_header=p1_line
|
|
|
1092 |
|
|
|
1093 |
elif p1_line[4:9] == "1.0.0":
|
|
|
1094 |
#P1 Timestamp (DSMR 4)
|
|
|
1095 |
#eg. 0-0:1.0.0(101209113020W)
|
|
|
1096 |
if p1_line[10:23] != "000101010000W":
|
|
|
1097 |
#Check if meter clock is running
|
|
|
1098 |
p1_timestamp="20"+p1_line[10:12]+"-"+p1_line[12:14]+"-"+p1_line[14:16]+" "+p1_line[16:18]+":"+p1_line[18:20]+":"+p1_line[20:22]
|
|
|
1099 |
else:
|
|
|
1100 |
print ("%s: warning: invalid P1-telegram date/time value '%s', system date/time used instead: '%s'" % (progname, p1_line[10:23], p1_timestamp) )
|
|
|
1101 |
|
|
|
1102 |
elif p1_line[4:9] == "0.2.8":
|
|
|
1103 |
#DSMR Version (DSMR V4)
|
|
|
1104 |
#eg. 1-3:0.2.8(40)
|
|
|
1105 |
p1_lastpos=len(p1_line)-1
|
|
|
1106 |
p1_dsmr_version=p1_line[10:p1_lastpos]
|
|
|
1107 |
|
|
|
1108 |
elif p1_line[4:10] == "96.1.1":
|
|
|
1109 |
#####
|
|
|
1110 |
#Channel 0 = E
|
|
|
1111 |
#####
|
|
|
1112 |
#Equipment identifier (Electricity)
|
|
|
1113 |
#eg. 0-0:96.1.1(204B413655303031353131323039393130)
|
|
|
1114 |
p1_lastpos=len(p1_line)-1
|
|
|
1115 |
p1_equipment_id=p1_line[11:p1_lastpos]
|
|
|
1116 |
|
|
|
1117 |
elif p1_line[4:9] == "1.8.1":
|
|
|
1118 |
#Meter Reading electricity delivered to client (normal tariff)
|
|
|
1119 |
#eg. 1-0:1.8.1(00721.000*kWh) (DSMR 3)
|
|
|
1120 |
#eg. 1-0:1.8.1(000038.851*kWh) (DSMR 4)
|
|
|
1121 |
# p1_meterreading_in_1=float(p1_line[10:19])
|
|
|
1122 |
# p1_unitmeterreading_in_1=p1_line[20:23]
|
|
|
1123 |
p1_lastpos=len(p1_line)-1
|
|
|
1124 |
p1_num_start = p1_line.find("(") +1
|
|
|
1125 |
p1_num_end = p1_line.find("*")
|
|
|
1126 |
p1_meterreading_in_1=float(p1_line[p1_num_start:p1_num_end])
|
|
|
1127 |
p1_unitmeterreading_in_1=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1128 |
elif p1_line[4:9] == "1.8.2":
|
|
|
1129 |
#Meter Reading electricity delivered to client (low tariff)
|
|
|
1130 |
#eg. 1-0:1.8.2(00392.000*kWh)
|
|
|
1131 |
# p1_meterreading_in_2=float(p1_line[10:19])
|
|
|
1132 |
# p1_unitmeterreading_in_2=p1_line[20:23]
|
|
|
1133 |
p1_lastpos=len(p1_line)-1
|
|
|
1134 |
p1_num_start = p1_line.find("(") +1
|
|
|
1135 |
p1_num_end = p1_line.find("*")
|
|
|
1136 |
p1_meterreading_in_2=float(p1_line[p1_num_start:p1_num_end])
|
|
|
1137 |
p1_unitmeterreading_in_2=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1138 |
elif p1_line[4:9] == "2.8.1":
|
|
|
1139 |
#Meter Reading electricity delivered by client (normal tariff)
|
|
|
1140 |
#eg. 1-0:2.8.1(00000.000*kWh)
|
|
|
1141 |
# p1_meterreading_out_1=float(p1_line[10:19])
|
|
|
1142 |
# p1_unitmeterreading_out_1=p1_line[20:23]
|
|
|
1143 |
p1_lastpos=len(p1_line)-1
|
|
|
1144 |
p1_num_start = p1_line.find("(") +1
|
|
|
1145 |
p1_num_end = p1_line.find("*")
|
|
|
1146 |
p1_meterreading_out_1=float(p1_line[p1_num_start:p1_num_end])
|
|
|
1147 |
p1_unitmeterreading_out_1=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1148 |
|
|
|
1149 |
elif p1_line[4:9] == "2.8.2":
|
|
|
1150 |
#Meter Reading electricity delivered by client (low tariff)
|
|
|
1151 |
#eg. 1-0:2.8.2(00000.000*kWh)
|
|
|
1152 |
# p1_meterreading_out_2=float(p1_line[10:19])
|
|
|
1153 |
# p1_unitmeterreading_out_2=p1_line[20:23]
|
|
|
1154 |
p1_lastpos=len(p1_line)-1
|
|
|
1155 |
p1_num_start = p1_line.find("(") +1
|
|
|
1156 |
p1_num_end = p1_line.find("*")
|
|
|
1157 |
p1_meterreading_out_2=float(p1_line[p1_num_start:p1_num_end])
|
|
|
1158 |
p1_unitmeterreading_out_2=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1159 |
|
|
|
1160 |
elif p1_line[4:11] == "96.14.0":
|
|
|
1161 |
#Tariff indicator electricity
|
|
|
1162 |
#eg. 0-0:96.14.0(0001)
|
|
|
1163 |
#alternative 0-0:96.14.0(1)
|
|
|
1164 |
p1_lastpos=len(p1_line)-1
|
|
|
1165 |
p1_current_tariff=int(p1_line[12:p1_lastpos])
|
|
|
1166 |
|
|
|
1167 |
elif p1_line[4:9] == "1.7.0":
|
|
|
1168 |
#Actual electricity power delivered to client (+P)
|
|
|
1169 |
#eg. 1-0:1.7.0(0000.91*kW)
|
|
|
1170 |
# p1_current_power_in=float(p1_line[10:17])
|
|
|
1171 |
# p1_unit_current_power_in=p1_line[18:20]
|
|
|
1172 |
p1_lastpos=len(p1_line)-1
|
|
|
1173 |
p1_num_start = p1_line.find("(") +1
|
|
|
1174 |
p1_num_end = p1_line.find("*")
|
|
|
1175 |
p1_current_power_in=float(p1_line[p1_num_start:p1_num_end])
|
|
|
1176 |
p1_unit_current_power_in=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1177 |
|
|
|
1178 |
elif p1_line[4:9] == "2.7.0":
|
|
|
1179 |
#Actual electricity power delivered by client (-P)
|
|
|
1180 |
#1-0:2.7.0(0000.00*kW)
|
|
|
1181 |
# p1_current_power_out=float(p1_line[10:17])
|
|
|
1182 |
# p1_unit_current_power_out=p1_line[18:20]
|
|
|
1183 |
p1_lastpos=len(p1_line)-1
|
|
|
1184 |
p1_num_start = p1_line.find("(") +1
|
|
|
1185 |
p1_num_end = p1_line.find("*")
|
|
|
1186 |
p1_current_power_out=float(p1_line[p1_num_start:p1_num_end])
|
|
|
1187 |
p1_unit_current_power_out=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1188 |
|
|
|
1189 |
elif p1_line[4:10] == "17.0.0":
|
|
|
1190 |
#Actual threshold Electricity
|
|
|
1191 |
#Companion standard, eg Kamstrup, Xemex
|
|
|
1192 |
#eg. 0-0:17.0.0(999*A)
|
|
|
1193 |
#Iskraemeco
|
|
|
1194 |
#eg. 0-0:17.0.0(0999.00*kW)
|
|
|
1195 |
p1_lastpos=len(p1_line)-1
|
|
|
1196 |
p1_num_start = p1_line.find("(") +1
|
|
|
1197 |
p1_num_end = p1_line.find("*")
|
|
|
1198 |
p1_current_threshold=float(p1_line[p1_num_start:p1_num_end])
|
|
|
1199 |
p1_unit_current_threshold=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1200 |
|
|
|
1201 |
elif p1_line[4:11] == "96.3.10":
|
|
|
1202 |
#Actual switch position Electricity (in/out/enabled).
|
|
|
1203 |
#eg. 0-0:96.3.10(1), default to 1
|
|
|
1204 |
p1_value=p1_line[12:13]
|
|
|
1205 |
if not isinstance(p1_value, int):
|
|
|
1206 |
p1_value=1
|
|
|
1207 |
p1_current_switch_position=int(p1_value)
|
|
|
1208 |
elif p1_line[4:11] == "96.7.21":
|
|
|
1209 |
#Number of powerfailures in any phase (DSMR4)
|
|
|
1210 |
#eg. 0-0:96.7.21(00004)
|
|
|
1211 |
p1_lastpos=len(p1_line)-1
|
|
|
1212 |
p1_num_start = p1_line.find("(") +1
|
|
|
1213 |
p1_powerfailures=int(float(p1_line[p1_num_start:p1_lastpos]))
|
|
|
1214 |
|
|
|
1215 |
elif p1_line[4:10] == "96.7.9":
|
|
|
1216 |
#Number of long powerfailures in any phase (DSMR4)
|
|
|
1217 |
#eg. 0-0:96.7.9(00002)
|
|
|
1218 |
p1_lastpos=len(p1_line)-1
|
|
|
1219 |
p1_num_start = p1_line.find("(") +1
|
|
|
1220 |
p1_long_powerfailures=int(float(p1_line[p1_num_start:p1_lastpos]))
|
|
|
1221 |
|
|
|
1222 |
elif p1_line[4:11] == "99.97.0":
|
|
|
1223 |
#Powerfailure eventlog (DSMR4)
|
|
|
1224 |
#eg. 1-0:99:97.0(2)(0:96.7.19)(101208152415W)(0000000240*s)(101208151004W)(00000000301*s)
|
|
|
1225 |
# 1-0:99.97.0(0)(0-0:96.7.19)
|
|
|
1226 |
p1_lastpos=len(p1_line)
|
|
|
1227 |
p1_log_start= p1_line.find("0:96.7.19") +10
|
|
|
1228 |
p1_long_powerfailures_log=p1_line[p1_log_start:p1_lastpos]
|
|
|
1229 |
|
|
|
1230 |
elif p1_line[4:11] == "32.32.0":
|
|
|
1231 |
#Number of Voltage sags L1 (DSMR4)
|
|
|
1232 |
#eg. 1-0:32.32.0(00002)
|
|
|
1233 |
p1_lastpos=len(p1_line)-1
|
|
|
1234 |
p1_num_start = p1_line.find("(") +1
|
|
|
1235 |
p1_voltage_sags_l1=int(float(p1_line[p1_num_start:p1_lastpos]))
|
|
|
1236 |
|
|
|
1237 |
elif p1_line[4:11] == "52.32.0":
|
|
|
1238 |
#Number of Voltage sags L2 (DSMR4)
|
|
|
1239 |
#eg. 1-0:52.32.0(00002)
|
|
|
1240 |
p1_lastpos=len(p1_line)-1
|
|
|
1241 |
p1_num_start = p1_line.find("(") +1
|
|
|
1242 |
p1_voltage_sags_l2=int(float(p1_line[p1_num_start:p1_lastpos]))
|
|
|
1243 |
|
|
|
1244 |
elif p1_line[4:11] == "72.32.0":
|
|
|
1245 |
#Number of Voltage sags L3 (DSMR4)
|
|
|
1246 |
#eg. 1-0:72.32.0(00002)
|
|
|
1247 |
p1_lastpos=len(p1_line)-1
|
|
|
1248 |
p1_num_start = p1_line.find("(") +1
|
|
|
1249 |
p1_voltage_sags_l3=int(float(p1_line[p1_num_start:p1_lastpos]))
|
|
|
1250 |
|
|
|
1251 |
elif p1_line[4:11] == "32.36.0":
|
|
|
1252 |
#Number of Voltage swells L1 (DSMR4)
|
|
|
1253 |
#eg. 1-0:32.36.0(00002)
|
|
|
1254 |
p1_lastpos=len(p1_line)-1
|
|
|
1255 |
p1_num_start = p1_line.find("(") +1
|
|
|
1256 |
p1_voltage_swells_l1=int(float(p1_line[p1_num_start:p1_lastpos]))
|
|
|
1257 |
|
|
|
1258 |
elif p1_line[4:11] == "52.36.0":
|
|
|
1259 |
#Number of Voltage swells L2 (DSMR4)
|
|
|
1260 |
#eg. 1-0:52.36.0(00002)
|
|
|
1261 |
p1_lastpos=len(p1_line)-1
|
|
|
1262 |
p1_num_start = p1_line.find("(") +1
|
|
|
1263 |
p1_voltage_swells_l2=int(float(p1_line[p1_num_start:p1_lastpos]))
|
|
|
1264 |
|
|
|
1265 |
elif p1_line[4:11] == "72.36.0":
|
|
|
1266 |
#Number of Voltage swells L3 (DSMR4)
|
|
|
1267 |
#eg. 1-0:72.36.0(00002)
|
|
|
1268 |
p1_lastpos=len(p1_line)-1
|
|
|
1269 |
p1_num_start = p1_line.find("(") +1
|
|
|
1270 |
p1_voltage_swells_l3=int(float(p1_line[p1_num_start:p1_lastpos]))
|
|
|
1271 |
|
|
|
1272 |
|
|
|
1273 |
elif p1_line[4:10] == "31.7.0":
|
|
|
1274 |
#Instantaneous current L1 in A (DSMR4)
|
|
|
1275 |
#eg. 1-0:31.7.0.255(001*A)
|
|
|
1276 |
p1_lastpos=len(p1_line)-1
|
|
|
1277 |
p1_num_start = p1_line.find("(") +1
|
|
|
1278 |
p1_num_end = p1_line.find("*")
|
|
|
1279 |
p1_instantaneous_current_l1=int(float(p1_line[p1_num_start:p1_num_end]))
|
|
|
1280 |
p1_unit_instantaneous_current_l1=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1281 |
|
|
|
1282 |
elif p1_line[4:10] == "51.7.0":
|
|
|
1283 |
#Instantaneous current L2 in A (DSMR4)
|
|
|
1284 |
#eg. 1-0:51.7.0.255(002*A)
|
|
|
1285 |
p1_lastpos=len(p1_line)-1
|
|
|
1286 |
p1_num_start = p1_line.find("(") +1
|
|
|
1287 |
p1_num_end = p1_line.find("*")
|
|
|
1288 |
p1_instantaneous_current_l2=int(float(p1_line[p1_num_start:p1_num_end]))
|
|
|
1289 |
p1_unit_instantaneous_current_l2=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1290 |
|
|
|
1291 |
|
|
|
1292 |
elif p1_line[4:10] == "71.7.0":
|
|
|
1293 |
#Instantaneous current L3 in A (DSMR4)
|
|
|
1294 |
#eg. 1-0:71.7.0.255(003*A)
|
|
|
1295 |
p1_lastpos=len(p1_line)-1
|
|
|
1296 |
p1_num_start = p1_line.find("(") +1
|
|
|
1297 |
p1_num_end = p1_line.find("*")
|
|
|
1298 |
p1_instantaneous_current_l3=int(float(p1_line[p1_num_start:p1_num_end]))
|
|
|
1299 |
p1_unit_instantaneous_current_l3=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1300 |
|
|
|
1301 |
elif p1_line[4:10] == "21.7.0":
|
|
|
1302 |
#Instantaneous active power L1 (+P) in W (DSMR4)
|
|
|
1303 |
#eg 1-0:21.7.0.255(01.111*kW)
|
|
|
1304 |
p1_lastpos=len(p1_line)-1
|
|
|
1305 |
p1_num_start = p1_line.find("(") +1
|
|
|
1306 |
p1_num_end = p1_line.find("*")
|
|
|
1307 |
p1_instantaneous_active_power_in_l1=int(float(p1_line[p1_num_start:p1_num_end]))
|
|
|
1308 |
p1_unit_instantaneous_active_power_in_l1=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1309 |
|
|
|
1310 |
elif p1_line[4:10] == "41.7.0":
|
|
|
1311 |
#Instantaneous active power L2 (+P) in W (DSMR4)
|
|
|
1312 |
#eg 1-0:41.7.0.255(02.222*kW)
|
|
|
1313 |
p1_lastpos=len(p1_line)-1
|
|
|
1314 |
p1_num_start = p1_line.find("(") +1
|
|
|
1315 |
p1_num_end = p1_line.find("*")
|
|
|
1316 |
p1_instantaneous_active_power_in_l2=int(float(p1_line[p1_num_start:p1_num_end]))
|
|
|
1317 |
p1_unit_instantaneous_active_power_in_l2=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1318 |
|
|
|
1319 |
elif p1_line[4:10] == "61.7.0":
|
|
|
1320 |
#Instantaneous active power L3 (+P) in W (DSMR4)
|
|
|
1321 |
#eg 1-0:61.7.0.255(03.333*kW)
|
|
|
1322 |
p1_lastpos=len(p1_line)-1
|
|
|
1323 |
p1_num_start = p1_line.find("(") +1
|
|
|
1324 |
p1_num_end = p1_line.find("*")
|
|
|
1325 |
p1_instantaneous_active_power_in_l3=int(float(p1_line[p1_num_start:p1_num_end]))
|
|
|
1326 |
p1_unit_instantaneous_active_power_in_l3=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1327 |
|
|
|
1328 |
elif p1_line[4:10] == "22.7.0":
|
|
|
1329 |
#Instantaneous active power L1 (+P) in W (DSMR4)
|
|
|
1330 |
#eg 1-0:22.7.0.255(04.444*kW)
|
|
|
1331 |
p1_lastpos=len(p1_line)-1
|
|
|
1332 |
p1_num_start = p1_line.find("(") +1
|
|
|
1333 |
p1_num_end = p1_line.find("*")
|
|
|
1334 |
p1_instantaneous_active_power_out_l1=int(float(p1_line[p1_num_start:p1_num_end]))
|
|
|
1335 |
p1_unit_instantaneous_active_power_out_l1=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1336 |
|
|
|
1337 |
elif p1_line[4:10] == "42.7.0":
|
|
|
1338 |
#Instantaneous active power L2 (+P) in W (DSMR4)
|
|
|
1339 |
#eg 1-0:42.7.0.255(05.555*kW)
|
|
|
1340 |
p1_lastpos=len(p1_line)-1
|
|
|
1341 |
p1_num_start = p1_line.find("(") +1
|
|
|
1342 |
p1_num_end = p1_line.find("*")
|
|
|
1343 |
p1_instantaneous_active_power_out_l2=int(float(p1_line[p1_num_start:p1_num_end]))
|
|
|
1344 |
p1_unit_instantaneous_active_power_out_l2=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1345 |
|
|
|
1346 |
elif p1_line[4:10] == "62.7.0":
|
|
|
1347 |
#Instantaneous active power L3 (+P) in W (DSMR4)
|
|
|
1348 |
#eg 1-0:62.7.0.255(06.666*kW)
|
|
|
1349 |
p1_lastpos=len(p1_line)-1
|
|
|
1350 |
p1_num_start = p1_line.find("(") +1
|
|
|
1351 |
p1_num_end = p1_line.find("*")
|
|
|
1352 |
p1_instantaneous_active_power_out_l3=int(float(p1_line[p1_num_start:p1_num_end]))
|
|
|
1353 |
p1_unit_instantaneous_active_power_out_l3=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1354 |
|
|
|
1355 |
elif p1_line[4:10] == "32.7.0":
|
|
|
1356 |
#Voltage level L1 in V (DSMR4)
|
|
|
1357 |
#1-0:32.7.0(00234*V)
|
|
|
1358 |
p1_lastpos=len(p1_line)-1
|
|
|
1359 |
p1_num_start = p1_line.find("(") +1
|
|
|
1360 |
p1_num_end = p1_line.find("*")
|
|
|
1361 |
p1_voltage_l1=int(float(p1_line[p1_num_start:p1_num_end]))
|
|
|
1362 |
p1_unit_voltage_l1=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1363 |
|
|
|
1364 |
elif p1_line[4:10] == "52.7.0":
|
|
|
1365 |
#Voltage level L2 in V (DSMR4)
|
|
|
1366 |
#1-0:52.7.0(00234*V)
|
|
|
1367 |
p1_lastpos=len(p1_line)-1
|
|
|
1368 |
p1_num_start = p1_line.find("(") +1
|
|
|
1369 |
p1_num_end = p1_line.find("*")
|
|
|
1370 |
p1_voltage_l2=int(float(p1_line[p1_num_start:p1_num_end]))
|
|
|
1371 |
p1_unit_voltage_l2=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1372 |
|
|
|
1373 |
elif p1_line[4:10] == "72.7.0":
|
|
|
1374 |
#Voltage level L3 in V (DSMR4)
|
|
|
1375 |
#1-0:72.7.0(00234*V)
|
|
|
1376 |
p1_lastpos=len(p1_line)-1
|
|
|
1377 |
p1_num_start = p1_line.find("(") +1
|
|
|
1378 |
p1_num_end = p1_line.find("*")
|
|
|
1379 |
p1_voltage_l3=int(float(p1_line[p1_num_start:p1_num_end]))
|
|
|
1380 |
p1_unit_voltage_l3=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1381 |
|
|
|
1382 |
elif p1_line[4:11] == "96.13.1":
|
|
|
1383 |
#Text message code: numeric 8 digits
|
|
|
1384 |
#eg. 0-0:96.13.1()
|
|
|
1385 |
p1_lastpos=len(p1_line)-1
|
|
|
1386 |
# p1_message_code=p1_line[12:p1_lastpos]
|
|
|
1387 |
p1_message_code=bytes.fromhex(p1_line[12:p1_lastpos]).decode('utf-8')
|
|
|
1388 |
elif p1_line[4:11] == "96.13.0":
|
|
|
1389 |
#Text message max 1024 characters.
|
|
|
1390 |
#eg. 0-0:96.13.0()
|
|
|
1391 |
p1_lastpos=len(p1_line)-1
|
|
|
1392 |
p1_message_text=bytes.fromhex(p1_line[12:p1_lastpos]).decode('utf-8')
|
|
|
1393 |
# p1_line[12:p1_lastpos]
|
|
|
1394 |
#####
|
|
|
1395 |
#Channels 1/2/3/4: MBus connected meters
|
|
|
1396 |
#####
|
|
|
1397 |
elif p1_line[4:10] == "24.1.0":
|
|
|
1398 |
#Device-Type
|
|
|
1399 |
#eg. 0-1:24.1.0(3)
|
|
|
1400 |
#or 0-1:24.1.0(03) 3=Gas;5=Heat;6=Cooling
|
|
|
1401 |
#or 0-1:24.1.0(03) 3/7=Gas;5=Heat;6=Cooling (Standard OBIS: 1-Electricity / 4-HeatCostAllocation / 5-Cooling / 6-Heat / 7-Gas / 8-ColdWater / 9-HotWater)
|
|
|
1402 |
|
|
|
1403 |
p1_channel=int(p1_line[2:3])
|
|
|
1404 |
p1_lastpos=len(p1_line)-1
|
|
|
1405 |
p1_value=int(p1_line[11:p1_lastpos])
|
|
|
1406 |
if p1_value in [3,7]:
|
|
|
1407 |
p1_value2="Gas"
|
|
|
1408 |
elif p1_value == 4:
|
|
|
1409 |
p1_value2="HeatCost"
|
|
|
1410 |
elif p1_value == 5:
|
|
|
1411 |
p1_value2="Heat"
|
|
|
1412 |
elif p1_value == 6:
|
|
|
1413 |
p1_value2="Cold"
|
|
|
1414 |
elif p1_value == 8:
|
|
|
1415 |
p1_value2="Cold water"
|
|
|
1416 |
elif p1_value == 9:
|
|
|
1417 |
p1_value2="Hot water"
|
|
|
1418 |
|
|
|
1419 |
else:
|
|
|
1420 |
p1_value2="Unknown"
|
|
|
1421 |
#self, id=None, type_id=None, type_desc=None, equipment_id=None, timestamp=None, meterreading=None, unit=None, valveposition=None
|
|
|
1422 |
if p1_channel==1:
|
|
|
1423 |
p1_channel_1.id=p1_channel
|
|
|
1424 |
p1_channel_1.type_id = p1_value
|
|
|
1425 |
p1_channel_1.type_desc= p1_value2
|
|
|
1426 |
elif p1_channel==2:
|
|
|
1427 |
p1_channel_2.id=p1_channel
|
|
|
1428 |
p1_channel_2.type_id = p1_value
|
|
|
1429 |
p1_channel_2.type_desc= p1_value2
|
|
|
1430 |
elif p1_channel==3:
|
|
|
1431 |
p1_channel_3.id=p1_channel
|
|
|
1432 |
p1_channel_3.type_id = p1_value
|
|
|
1433 |
p1_channel_3.type_desc= p1_value2
|
|
|
1434 |
elif p1_channel==4:
|
|
|
1435 |
p1_channel_4.id=p1_channel
|
|
|
1436 |
p1_channel_4.type_id = p1_value
|
|
|
1437 |
p1_channel_4.type_desc= p1_value2
|
|
|
1438 |
|
|
|
1439 |
|
|
|
1440 |
elif p1_line[4:10] == "96.1.0":
|
|
|
1441 |
#Equipment identifier
|
|
|
1442 |
#eg. 0-1:96.1.0(3238303039303031303434303132303130)
|
|
|
1443 |
p1_channel=int(p1_line[2:3])
|
|
|
1444 |
p1_lastpos=len(p1_line)-1
|
|
|
1445 |
p1_value=p1_line[11:p1_lastpos]
|
|
|
1446 |
#self, id=None, type_id=None, type_desc=None, equipment_id=None, timestamp=None, meterreading=None, unit=None, valveposition=None
|
|
|
1447 |
if p1_channel==1:
|
|
|
1448 |
p1_channel_1.equipment_id=p1_value
|
|
|
1449 |
elif p1_channel==2:
|
|
|
1450 |
p1_channel_2.equipment_id=p1_value
|
|
|
1451 |
elif p1_channel==3:
|
|
|
1452 |
p1_channel_3.equipment_id=p1_value
|
|
|
1453 |
elif p1_channel==4:
|
|
|
1454 |
p1_channel_4.equipment_id=p1_value
|
|
|
1455 |
|
|
|
1456 |
elif p1_line[4:10] == "24.3.0":
|
|
|
1457 |
#Last hourly value delivered to client (DSMR < V4)
|
|
|
1458 |
#eg. Kamstrup/Iskraemeco:
|
|
|
1459 |
#0-1:24.3.0(110403140000)(000008)(60)(1)(0-1:24.2.1)(m3)
|
|
|
1460 |
#(00437.631)
|
|
|
1461 |
#eg. Companion Standard:
|
|
|
1462 |
#0-1:24.3.0(110403140000)(000008)(60)(1)(0-1:24.2.1)(m3)(00437.631)
|
|
|
1463 |
p1_channel=int(p1_line[2:3])
|
|
|
1464 |
p1_channel_timestamp="20"+p1_line[11:13]+"-"+p1_line[13:15]+"-"+p1_line[15:17]+" "+p1_line[17:19]+":"+p1_line[19:21]+":"+p1_line[21:23]
|
|
|
1465 |
p1_lastpos=len(p1_line)-1
|
|
|
1466 |
#Value is in next line
|
|
|
1467 |
p1_unit=p1_line[p1_lastpos-2:p1_lastpos]
|
|
|
1468 |
p1_raw = ser.readline()
|
|
|
1469 |
# p1_str=str(p1_raw, "utf-8")
|
|
|
1470 |
p1_str=p1_raw
|
|
|
1471 |
if comport != 0:
|
|
|
1472 |
p1_str=str(p1_raw, "utf-8")
|
|
|
1473 |
p1_line=p1_str.strip()
|
|
|
1474 |
#self, id=None, type_id=None, type_desc=None, equipment_id=None, timestamp= None, meterreading=None, unit=None, valveposition=None
|
|
|
1475 |
if p1_channel==1:
|
|
|
1476 |
p1_channel_1.timestamp=p1_channel_timestamp
|
|
|
1477 |
p1_channel_1.meterreading=float(p1_line[1:10])
|
|
|
1478 |
p1_channel_1.unit=p1_unit
|
|
|
1479 |
elif p1_channel==2:
|
|
|
1480 |
p1_channel_2.timestamp=p1_channel_timestamp
|
|
|
1481 |
p1_channel_2.meterreading=float(p1_line[1:10])
|
|
|
1482 |
p1_channel_2.unit=p1_unit
|
|
|
1483 |
elif p1_channel==3:
|
|
|
1484 |
p1_channel_3.timestamp=p1_channel_timestamp
|
|
|
1485 |
p1_channel_3.meterreading=float(p1_line[1:10])
|
|
|
1486 |
p1_channel_3.unit=p1_unit
|
|
|
1487 |
elif p1_channel==4:
|
|
|
1488 |
p1_channel_4.timestamp=p1_channel_timestamp
|
|
|
1489 |
p1_channel_4.meterreading=float(p1_line[1:10])
|
|
|
1490 |
p1_channel_4.unit=p1_unit
|
|
|
1491 |
|
|
|
1492 |
elif p1_line[4:10] == "24.2.1":
|
|
|
1493 |
#Last hourly value delivered to client (DSMR v4)
|
|
|
1494 |
#eg. 0-1:24.2.1(101209110000W)(12785.123*m3)
|
|
|
1495 |
p1_channel=int(p1_line[2:3])
|
|
|
1496 |
p1_channel_timestamp="20"+p1_line[11:13]+"-"+p1_line[13:15]+"-"+p1_line[15:17]+" "+p1_line[17:19]+":"+p1_line[19:21]+":"+p1_line[21:23]
|
|
|
1497 |
p1_lastpos=len(p1_line)-1
|
|
|
1498 |
p1_line=p1_line[25:p1_lastpos]
|
|
|
1499 |
p1_lastpos=len(p1_line)
|
|
|
1500 |
p1_num_start = p1_line.find("(") +1
|
|
|
1501 |
p1_num_end = p1_line.find("*")
|
|
|
1502 |
p1_value=float(p1_line[p1_num_start:p1_num_end])
|
|
|
1503 |
p1_unit=p1_line[p1_num_end+1:p1_lastpos]
|
|
|
1504 |
#self, id=None, type_id=None, type_desc=None, equipment_id=None, timestamp= None, meterreading=None, unit=None, valveposition=None
|
|
|
1505 |
if p1_channel==1:
|
|
|
1506 |
p1_channel_1.timestamp=p1_channel_timestamp
|
|
|
1507 |
p1_channel_1.meterreading=p1_value
|
|
|
1508 |
p1_channel_1.unit=p1_unit
|
|
|
1509 |
elif p1_channel==2:
|
|
|
1510 |
p1_channel_2.timestamp=p1_channel_timestamp
|
|
|
1511 |
p1_channel_2.meterreading=p1_value
|
|
|
1512 |
p1_channel_2.unit=p1_unit
|
|
|
1513 |
elif p1_channel==3:
|
|
|
1514 |
p1_channel_3.timestamp=p1_channel_timestamp
|
|
|
1515 |
p1_channel_3.meterreading=p1_value
|
|
|
1516 |
p1_channel_3.unit=p1_unit
|
|
|
1517 |
elif p1_channel==4:
|
|
|
1518 |
p1_channel_4.timestamp=p1_channel_timestamp
|
|
|
1519 |
p1_channel_4.meterreading=p1_value
|
|
|
1520 |
p1_channel_4.unit=p1_unit
|
|
|
1521 |
|
|
|
1522 |
elif p1_line[4:10] == "24.4.0":
|
|
|
1523 |
#Valve position (on/off/released)
|
|
|
1524 |
#eg. 0-1:24.4.0()
|
|
|
1525 |
#eg. 0-1:24.4.0(1)
|
|
|
1526 |
#Valveposition defaults to '1'(=Open) if invalid value
|
|
|
1527 |
p1_channel=int(p1_line[2:3])
|
|
|
1528 |
p1_lastpos=len(p1_line)-1
|
|
|
1529 |
p1_value=p1_line[12:p1_lastpos].strip()
|
|
|
1530 |
if not isinstance(p1_value, int):
|
|
|
1531 |
p1_value=1
|
|
|
1532 |
if p1_channel==1:
|
|
|
1533 |
p1_channel_1.valveposition=p1_value
|
|
|
1534 |
elif p1_channel==2:
|
|
|
1535 |
p1_channel_2.valveposition=p1_value
|
|
|
1536 |
elif p1_channel==3:
|
|
|
1537 |
p1_channel_3.valveposition=p1_value
|
|
|
1538 |
elif p1_channel==4:
|
|
|
1539 |
p1_channel_4.valveposition=p1_value
|
|
|
1540 |
|
|
|
1541 |
elif p1_line[0:1] == "" or p1_line[0:1] == " ":
|
|
|
1542 |
#Empty line
|
|
|
1543 |
p1_value=""
|
|
|
1544 |
|
|
|
1545 |
elif p1_line[0:1] == "!":
|
|
|
1546 |
#in DSMR 4 telegrams there might be a checksum following the "!".
|
|
|
1547 |
#eg. !141B
|
|
|
1548 |
#CRC16 value calculated over the preceding characters in the data message (from “/” to “!” using the polynomial: x16+x15+x2+1).
|
|
|
1549 |
#the checksum is discarded
|
|
|
1550 |
|
|
|
1551 |
#End of P1 telegram
|
|
|
1552 |
#Output if a complete telegram and matching log_interval
|
|
|
1553 |
if p1_teller == log_interval:
|
|
|
1554 |
################################################################
|
|
|
1555 |
#Start of functionality to add other meterdata to p1-telegram #
|
|
|
1556 |
################################################################
|
|
|
1557 |
#Comment out / remove when not applicable #
|
|
|
1558 |
################################################################
|
|
|
1559 |
if import_db:
|
|
|
1560 |
######################HEAT: Mandatory 1st ChannelID, 1st ChannelDataElement, optional 2nd ChannelID, 2nd ChannelDataElement
|
|
|
1561 |
get_heat_data(1,p1_channel_1,2,p1_channel_2)
|
|
|
1562 |
######################POWER SUB METERING: ChannelID, ChannelDataElement, TypeID, TypeDescription
|
|
|
1563 |
# get_power_data(#,p1_channel_#,1,"E-Production volume")
|
|
|
1564 |
######################S0 SUB METERING: S0-ID, S0-Register, ChannelID, ChannelDataElement, TypeID, TypeDescription
|
|
|
1565 |
# get_s0_data('25325','1',3,p1_channel_3,1,"E-Production volume")
|
|
|
1566 |
######################PV INVERTER: Mandatory 1st ChannelID, 1st ChannelDataElement, optional 2nd ChannelID, 2nd ChannelDataElement
|
|
|
1567 |
# get_pv_data(1,p1_channel_1,2,p1_channel_2)
|
|
|
1568 |
################################################################
|
|
|
1569 |
#End of functionality to add other meterdata to p1-telegram #
|
|
|
1570 |
################################################################
|
|
|
1571 |
#Output to screen
|
|
|
1572 |
if output_mode=="screen": print_p1_telegram()
|
|
|
1573 |
#Output to csv_file
|
|
|
1574 |
if output_mode=="csv": csv_p1_telegram()
|
|
|
1575 |
#Output to database
|
|
|
1576 |
if output_mode=="db":
|
|
|
1577 |
db_p1_telegram()
|
|
|
1578 |
db_p2_telegram()
|
|
|
1579 |
db_p3_telegram()
|
|
|
1580 |
#Output to PVOutput.org
|
|
|
1581 |
if pvo_output: pvo_p1_telegram()
|
|
|
1582 |
################################################################
|
|
|
1583 |
p1_teller=0
|
|
|
1584 |
p1_telegram=False
|
|
|
1585 |
#to facilitate testing, when reading p1test.log always wait 10 seconds before proceeding to next telegram to simulate actual meter behaviour
|
|
|
1586 |
if comport == 0: sleep(10)
|
|
|
1587 |
else:
|
|
|
1588 |
#Always dump unrecognized data in identified telegram to screen
|
|
|
1589 |
print ("Error interpreting P1-telegram, unrecognized data encountered: '%s'" % p1_line )
|
|
|
1590 |
# elif p1_line != '':
|
|
|
1591 |
#Always dump unrecognized data in identified telegram to screen
|
|
|
1592 |
# print ("Fout bij analyseren P1 data, nog geen compleet P1-telegram ontvangen: '%s'" % p1_line )
|
|
|
1593 |
|
|
|
1594 |
#Close port and show status
|
|
|
1595 |
try:
|
|
|
1596 |
ser.close()
|
|
|
1597 |
except:
|
|
|
1598 |
if win_os:
|
|
|
1599 |
sys.exit ("Error closing %s. Program aborted." % ser.name)
|
|
|
1600 |
else:
|
|
|
1601 |
sys.exit ("Error closing %s. Program aborted." % port)
|
|
|
1602 |
|
|
|
1603 |
|
|
|
1604 |
|
|
|
1605 |
|
|
|
1606 |
|
|
|
1607 |
|
|
|
1608 |
|
|
|
1609 |
|
|
|
1610 |
|
|
|
1611 |
|