Subversion Repositories Python_UH50_Script

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 raymond 1
#
2
# Landi&Gyr UH50 IR Datalogger
3
# $Revision: 9 $
4
# $Author: raymond $
5
# $Date: 2015-09-06 13:21:04 +0200 (zo, 06 sep 2015) $
6
# Copyright (c) 2013 J. van der Linde
7
#
8
# Although there is a explicit copyright on this sourcecode, anyone may use it
9
# freely under a  "Creative Commons
10
# Naamsvermelding-NietCommercieel-GeenAfgeleideWerken 3.0 Nederland" licentie.
11
# Please check http://creativecommons.org/licenses/by-nc-nd/3.0/nl/ for details
12
#
13
# This software is provided as is and comes with absolutely no warranty.
14
# The author is not responsible or liable (direct or indirect) to anyone for
15
# the use or misuse of this software. Any person using this software does so
16
# entirely at his/her own risk.  That person bears sole responsibility and
17
# liability for any claims or actions, legal or civil, arising from such use.
18
# If you believe this software is in breach of anyone's copyright you will
19
# inform the author immediately so the offending material can be removed upon
20
# receipt of proof of copyright for that material.
21
#
22
# Dependend on Python 3.2+ and Python 3.2+ packages: PySerial 2.5
23
#
24
 
25
version = "UH50 v0.10 RVS"
26
import sys
27
import glob
28
import serial
29
import datetime
30
import csv
31
import os
32
import locale
33
from time import sleep
34
 
35
MySQL_loaded=True
36
try:
37
    import mysql.connector
38
except ImportError:
39
    MySQL_loaded=False
40
 
41
def scan_serial():
42
# scan for available ports. return a list of tuples (num, name)
43
    """ Lists serial port names
44
 
45
        :raises EnvironmentError:
46
            On unsupported or unknown platforms
47
        :returns:
48
            A list of the serial ports available on the system
49
    """
50
    if sys.platform.startswith('win'):
51
        ports = ['COM%s' % (i + 1) for i in range(256)]
52
    elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
53
        # this excludes your current terminal "/dev/tty"
54
        ports = glob.glob('/dev/tty[A-Za-z]*')
55
    elif sys.platform.startswith('darwin'):
56
        ports = glob.glob('/dev/tty.*')
57
    else:
58
        raise EnvironmentError('Unsupported platform')
59
 
60
    port_exceptions = ['/dev/ttyprintk','dev/ttyprintk']
61
    for port in port_exceptions:
62
        if port in ports:
63
            ports.remove(port)
64
 
65
    available = []
66
    for port in ports:
67
        try:
68
            s = serial.Serial(port)
69
            s.close()
70
            available.append(port)
71
        except (OSError, serial.SerialException):
72
            pass
73
    if not available:
74
            available.append('Helaas geen seriele poorten gevonden')
75
    return available
76
 
77
################
78
#Error display #
79
################
80
def show_error():
81
    ft = sys.exc_info()[0]
82
    fv = sys.exc_info()[1]
83
    print("Fout type: %s" % ft )
84
    print("Fout waarde: %s" % fv )
85
    return
86
 
87
################
88
#Scherm output #
89
################
90
def print_heat_telegram():
91
    print ("---------------------------------------------------------------------------------------")
92
    print ("Landis & Gyr UH50 telegram ontvangen op: %s" % heat_timestamp)
93
    print ("Meter fabrikant/type: Landis & Gyr Ultraheat 50")
94
    print (" 0. 0 - Meter identificatie: %s" % heat_equipment_id )
95
    print (" 6. 8 - Meterstand Energie: %0.3f %s" % (heat_meterreading_energy, heat_unitmeterreading_energy) )
96
    print (" 6.26 - Meterstand Volume: %0.3f %s" % (heat_meterreading_volume, heat_unitmeterreading_volume) )
97
    print (" 6.31 - Meterstand Gebruiksduur: %0.3f %s" % (heat_meterreading_hours, heat_unitmeterreading_hours) )    
98
    print ("Einde UH50 telegram" )
99
    return        
100
 
101
################
102
#Csv output #
103
################
104
def csv_heat_telegram():
105
#New filename every day
106
    csv_filename=datetime.datetime.strftime(datetime.datetime.today(), "UH50_"+"%Y-%m-%d"+".csv" )
107
    try:
108
#If csv_file exists: open it
109
        csv_file=open(csv_filename, 'rt')
110
        csv_file.close()
111
        csv_file=open(csv_filename, 'at', newline='', encoding="utf-8")
112
        writer = csv.writer(csv_file, dialect='excel', delimiter=';', quoting=csv.QUOTE_NONNUMERIC)
113
    except IOError:
114
#Otherwise: create it
115
        csv_file=open(csv_filename, 'wt', newline='', encoding="utf-8")
116
        writer = csv.writer(csv_file, dialect='excel', delimiter=';', quoting=csv.QUOTE_NONNUMERIC)
117
#Write csv-header
118
        writer.writerow([
119
         'heat_timestamp', 
120
         'heat_equipment_id',
121
         'heat_meterreading_energy', 
122
         'heat_unitmeterreading_energy', 
123
         'heat_meterreading_volume', 
124
         'heat_unitmeterreading_volume', 
125
         'heat_meterreading_hours', 
126
         'heat_unitmeterreading_hours']) 
127
    print ("UH50 telegram in %s gelogd op: %s" % (csv_filename, heat_timestamp) )
128
    writer.writerow([
129
         heat_timestamp, 
130
         heat_equipment_id,
131
         heat_meterreading_energy, 
132
         heat_unitmeterreading_energy, 
133
         heat_meterreading_volume, 
134
         heat_unitmeterreading_volume, 
135
         heat_meterreading_hours, 
136
         heat_unitmeterreading_hours ])
137
    csv_file.close()
138
 
139
    return        
140
 
141
################
142
#DB output     #
143
################
144
def db_heat_telegram():
145
    query = "insert into heat_log values (\'" + \
146
         heat_timestamp  + "\',\'" + \
147
         heat_equipment_id + "\',\'" + \
148
         str(heat_meterreading_energy) + "\',\'" + \
149
         heat_unitmeterreading_energy + "\',\'" + \
150
         str(heat_meterreading_volume) + "\',\'" + \
151
         heat_unitmeterreading_volume + "\',\'" + \
152
         str(heat_meterreading_hours) + "\',\'" + \
153
         heat_unitmeterreading_hours + "\')"
154
 
155
#   print(query)
156
 
157
    try:
158
        db = mysql.connector.connect(user=p1_mysql_user, password=p1_mysql_passwd, host=p1_mysql_host, database=p1_mysql_db)
159
        c = db.cursor()
160
        c.execute (query)
161
        db.commit()
162
        print ("UH50 telegram in database %s / %s gelogd op: %s" % (p1_mysql_host, p1_mysql_db, heat_timestamp) )
163
        db.close()
164
    except:
165
        show_error()
166
        print ("Fout bij het openen van / schrijven naar database %s / %s. UH50 Telegram wordt gelogd in csv-bestand."  % (p1_mysql_host, p1_mysql_db))       
167
        csv_heat_telegram()
168
    return    
169
 
170
 
171
################################################################################################################################################
172
#Main program
173
################################################################################################################################################
174
print ("Landis & Gyr IR Datalogger %s" % version)
175
equipment_prefix = "UH50"
176
comport=0
177
output_mode="scherm"
178
win_os = (os.name == 'nt')
179
if win_os:
180
    print("Windows Mode")
181
else:
182
    print("Non-Windows Mode")
183
print("Python versie %s.%s.%s" % sys.version_info[:3]) 
184
#if not MySQL_Loaded==False:
185
#    print("MySQL Connector/Python niet gevonden. Database uitvoer niet mogelijk")
186
print ("Control-C om af te breken")
187
 
188
 
189
#comport parameters
190
try:
191
    comport=int(sys.argv[1])
192
except:
193
    print ("Opstart syntaxis: 'heat.py {COM poort-nummer} {uitvoer-modus} {db_host} {db_user} {db_password} {db_database}'")
194
    print ("Ontbrekende of verkeerde parameter: COM poort-nummer.")
195
    print ("Toegestane waarden:")
196
#scanserial returns win_os serial ports and non win_os USB serial ports
197
    print (scan_serial())
198
    print ("Programma afgebroken.")
199
    sys.exit()
200
 
201
#output_mode parameters
202
try:
203
    output_mode=sys.argv[2]
204
except:
205
    print ("Opstart syntaxis: 'heat.py {COM poort-nummer} {uitvoer-modus} {db_host} {db_user} {db_password} {db_database}'")
206
    print ("Ontbrekende of verkeerde parameters: ")
207
    print ("- Uitvoer-modus. Geldige waarden: 'scherm', 'csv', 'db'. 'scherm' gebruikt")
208
    output_mode="scherm"
209
if output_mode not in ["scherm", "csv", "db"]:
210
    print ("Opstart syntaxis: 'heat.py {COM poort-nummer} {uitvoer-modus} {db_host} {db_user} {db_password} {db_database}'")
211
    print ("Ontbrekende of verkeerde parameters: ")
212
    print ("- Uitvoer-modus. Geldige waarden: 'scherm', 'csv', 'db'. 'scherm' gebruikt")
213
    output_mode="scherm"
214
 
215
#database parameters    
216
if output_mode == "db" and MySQL_loaded:     
217
    try:
218
        p1_mysql_host=sys.argv[3]
219
        p1_mysql_user=sys.argv[4]
220
        p1_mysql_passwd=sys.argv[5]
221
        p1_mysql_db=sys.argv[6]
222
    except:
223
        print ("Opstart syntaxis: 'heat.py {COM poort-nummer} {uitvoer-modus} {db_host} {db_user} {db_password} {db_database}'")
224
        print ("Ontbrekende of verkeerde parameters: ")
225
        print ("- db_host. 'localhost' gebruikt")
226
        print ("- db_user. 'root' gebruikt")
227
        print ("- db_password. 'password' gebruikt")
228
        print ("- db_database. 'p1' gebruikt")
229
        p1_mysql_host='localhost'
230
        p1_mysql_user='root'
231
        p1_mysql_passwd='password'
232
        p1_mysql_db='p1'        
233
 
234
if output_mode == "db" and not MySQL_loaded:
235
    print ("Opstart syntaxis: 'heat.py {COM poort-nummer} {uitvoer-modus} {db_host} {db_user} {db_password} {db_database}'")
236
    print ("Ontbrekende of verkeerde parameters: ")
237
    print ("- Uitvoer-modus. MySQL Connector/Python niet gevonden. Uitvoer-modus 'db' niet toegestaan. Uitvoer-modus 'csv' gebruikt")
238
    output_mode = "csv"        
239
 
240
 
241
#Set COM port config
242
#if comport != 0:
243
#    ser = serial.Serial(
244
#    baudrate = 300,
245
#    bytesize=serial.SEVENBITS,
246
#    parity=serial.PARITY_EVEN,
247
#    stopbits=1,
248
#    xonxoff=0,
249
#    rtscts=0,
250
#    timeout=2,
251
#    port="/dev/ttyAMA0" 
252
#   )
253
ser = serial.Serial("/dev/ttyAMA0", baudrate=300, bytesize=7, parity="E", stopbits=1, timeout=2, xonxoff=0, rtscts=0)
254
#Show startup arguments 
255
print ("Opstart parameters:")   
256
if comport != 0: 
257
        if win_os:
258
            print ("COM poort-nummer: %d (%s)" % (comport, ser.name) )        
259
        else:
260
# ser.name property is not available in Linux.        
261
            port="/dev/ttyAMA"+str(comport-1)  # Linux Style for /dev/ttyAMA0, /dev/ttyUSB1, etc...
262
            print ("COM poort-nummer: %d (%s)" % (comport, port) )
263
else:
264
    print ("COM poort-nummer: NVT, Interne testdata wordt gebruikt")
265
print ("Uitvoer-modus: %s" % output_mode )
266
if output_mode == "db": 
267
    print ("MySQL-verbinding: %s / %s" % (p1_mysql_host, p1_mysql_db) )
268
 
269
if comport == 0:
270
#################################################################
271
# Use test values instead of COM port reading                   #
272
#################################################################  
273
    ir_buffer = "/LUGC2WR5\r\n"
274
    ir_lines = ir_buffer.strip().split('\r\n')
275
    ir_buffer = "6.8(0347.292*GJ)6.26(02647.89*m3)9.21(65298392)\r\n"
276
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
277
    ir_buffer = "6.26*01(02378.83*m3)6.8*01(0311.399*GJ)\r\n"
278
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
279
    ir_buffer = "F(0)9.20(65298392)6.35(60*m)\r\n"
280
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
281
    ir_buffer = "6.6(0023.8*kW)6.6*01(0023.8*kW)6.33(000.636*m3ph)9.4(099*C&090*C)\r\n"
282
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
283
    ir_buffer = "6.31(0069294*h)6.32(0000343*h)9.22(R)9.6(000&65298392&0)9.7(20000)\r\n"
284
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
285
    ir_buffer = "6.32*01(0000343*h)6.36(01-01)6.33*01(000.636*m3ph)\r\n"
286
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
287
    ir_buffer = "6.8.1()6.8.2()6.8.3()6.8.4()6.8.5()\r\n"
288
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
289
    ir_buffer = "6.8.1*01()6.8.2*01()6.8.3*01()\r\n"
290
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
291
    ir_buffer = "6.8.4*01()6.8.5*01()\r\n"
292
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
293
    ir_buffer = "9.4*01(099*C&090*C)\r\n"
294
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
295
    ir_buffer = "6.36.1(2006-02-17)6.36.1*01(2006-02-17)\r\n"
296
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
297
    ir_buffer = "6.36.2(2011-12-21)6.36.2*01(2011-12-21)\r\n"
298
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
299
    ir_buffer = "6.36.3(2006-03-23)6.36.3*01(2006-03-23)\r\n"
300
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
301
    ir_buffer = "6.36.4(2006-02-21)6.36.4*01(2006-02-21)\r\n"
302
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
303
    ir_buffer = "6.36.5(2000-00-00)6.36*02(01)9.36(2013-10-04&12:56:50)9.24(1.5*m3ph)\r\n"
304
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
305
    ir_buffer = "9.17(0)9.18()9.19()9.25()\r\n"
306
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
307
    ir_buffer = "9.1(0&1&0&-&CV&3&2.20)9.2(&&)0.0(65298392)!\r\n"
308
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
309
    ir_buffer = "h0\r\n"
310
    ir_lines.extend(ir_buffer.strip().split('\r\n'))  
311
else:  
312
#################################################################
313
# COM port reading                                              #
314
#################################################################    
315
    #Open COM port
316
    try:
317
        ser = serial.Serial("/dev/ttyAMA0", baudrate=300, bytesize=7, parity="E", stopbits=1, timeout=2, xonxoff=0, rtscts=0)
318
#        ser.open()
319
    except:
320
        if win_os:
321
            sys.exit ("Fout bij het openen van %s. Programma afgebroken."  % ser.name)
322
        else:
323
            sys.exit ("Fout bij het openen van %s. Programma afgebroken."  %  port) 
324
    print ("Activatie poort.")
325
    # Wake up
326
#    ser.setRTS(False)
327
#    ser.setDTR(False)
328
    sleep(5)
329
#    ser.setDTR(True)
330
#    ser.setRTS(True)
331
    ir_command=("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2F\x3F\x21\x0D\x0A")
332
    ser.write(ir_command.encode('utf-8')) 
333
    sleep(1.5)
334
    #Initialize
335
    print ("Initialisatie op 300 baud")
336
    ir_command='/?!\x0D\x0A'
337
    ser.write(ir_command.encode('utf-8'))
338
    ser.flush()
339
    #Wait for initialize confirmation
340
    ir_buffer = ''
341
    while '/LUGCUH50\r\n' not in ir_buffer:
342
        ir_buffer = str(ser.readline(), "utf-8")
343
        if '/?!\x0D\x0A' in ir_buffer:
344
            ir_buffer = str(ser.readline(), "utf-8")
345
    ir_lines = ir_buffer.strip().split('\r\n')
346
 
347
    print ("Gegevensuitwisseling op 2400 baud")
348
    #Set to 2400baud
349
    ser.baudrate = 2400
350
 
351
    #Wait for data
352
    ir_buffer = ''
353
    ETX = False
354
    while not ETX:
355
        ir_buffer = str(ser.readline(), "utf-8")
356
        if '\x03' in ir_buffer:
357
            ETX = True
358
    #Strip the STX character
359
        ir_buffer = ir_buffer.replace('\x02','')
360
    #Strip the ! character
361
        ir_buffer = ir_buffer.replace('!','')
362
    #Strip the ETX character
363
        ir_buffer = ir_buffer.replace('\x03','')
364
        ir_lines.extend(ir_buffer.strip().split('\r\n'))
365
    print ("Gegevensuitwisseling voltooid")
366
    #Close port and show status
367
    try:
368
        ser.close()
369
    except:
370
        if win_os:
371
            sys.exit ("Fout bij het sluiten van %s. Programma afgebroken."  % ser.name)
372
        else:
373
            sys.exit ("Fout bij het sluiten van %s. Programma afgebroken."  %  port)  
374
 
375
#################################################################
376
# Process data                                                  #
377
#################################################################           
378
#print ("Number of received elements: %d" % len(ir_lines))
379
#print ("Array of received elements: %s" % ir_lines)
380
 
381
heat_timestamp=datetime.datetime.strftime(datetime.datetime.today(), "%Y-%m-%d %H:%M:%S" )
382
heat_data = ir_lines
383
num_elements = len(ir_lines)
384
#print("Number of elements: %d"% num_elements)
385
#parse all heat_data elements
386
i=0
387
while i<num_elements:
388
#    print("Elements index: %d"% i)
389
    heat_element = heat_data[i]
390
#    print(heat_element)
391
 
392
    if heat_element.find("0.0(")!=-1:
393
    #heat_equipment_id 
394
    #0.0(11 digits C/N)
395
        heat_num_start=heat_element.find("0.0(")+4
396
        heat_num_end=heat_element.find(")",heat_num_start)
397
        heat_equipment_id = equipment_prefix + "_" + heat_element[heat_num_start:heat_num_end]
398
 
399
    if heat_element.find("6.8(")!=-1:
400
    #heat_meterreading_energy, heat_unitmeterreading_energy
401
    #6.8(Energy * unit)
402
        heat_num_start = heat_element.find("6.8(") +4
403
        heat_num_end=heat_element.find("*",heat_num_start)
404
        heat_meterreading_energy = float(heat_element[heat_num_start:heat_num_end])
405
        heat_num_start = heat_num_end+1
406
        heat_num_end=heat_element.find(")",heat_num_start)
407
        heat_unitmeterreading_energy = heat_element[heat_num_start:heat_num_end]
408
 
409
    if heat_element.find("6.26(")!=-1:
410
    #heat_meterreading_volume, heat_unitmeterreading_volume
411
    #6.26(Volume * m3)
412
        heat_num_start = heat_element.find("6.26(") +5
413
        heat_num_end=heat_element.find("*",heat_num_start)
414
        heat_meterreading_volume = float(heat_element[heat_num_start:heat_num_end])
415
        heat_num_start = heat_num_end+1
416
        heat_num_end=heat_element.find(")",heat_num_start)
417
        heat_unitmeterreading_volume = heat_element[heat_num_start:heat_num_end]
418
 
419
    if heat_element.find("6.31(")!=-1:
420
    #heat_meterreading_hours, heat_unitmeterreading_hours
421
    #6.31(Hours * h)
422
        heat_num_start = heat_element.find("6.31(") +5
423
        heat_num_end=heat_element.find("*",heat_num_start)
424
        heat_meterreading_hours = float(heat_element[heat_num_start:heat_num_end])
425
        heat_num_start = heat_num_end+1
426
        heat_num_end=heat_element.find(")",heat_num_start)
427
        heat_unitmeterreading_hours = heat_element[heat_num_start:heat_num_end]
428
 
429
    i+=1
430
#################################################################
431
# Output based on startup parameter 'output_mode'               #
432
#################################################################   
433
#Output to scherm
434
if output_mode=="scherm": print_heat_telegram()
435
#Output to csv_file
436
if output_mode=="csv": csv_heat_telegram()
437
#Output to database
438
if output_mode=="db": db_heat_telegram()
439
 
440
 
441
 
442
 
443
 
444
 
445
 
446
 
447
 
448