changeset 15:c04c75360a3b

Fix timezone screw up. Remove cut & paste code from the AGL script
author Daniel O'Connor <darius@dons.net.au>
date Fri, 23 Feb 2018 14:57:45 +1030
parents aa18210c2703
children 29a61ec4755b
files graph.py
diffstat 1 files changed, 19 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/graph.py	Thu Jan 11 08:43:40 2018 +1030
+++ b/graph.py	Fri Feb 23 14:57:45 2018 +1030
@@ -114,10 +114,6 @@
         args.start = args.start.replace(tzinfo = lt)
     if args.end.tzinfo == None:
         args.end = args.end.replace(tzinfo = lt)
-    startlt = args.start
-    endlt = args.end
-    args.start = args.start.astimezone(utc)
-    args.end = args.end.astimezone(utc)
     graph(args.graphfn, cur, cols, args.start, args.end, lt, utc)
 
 def graph(fname, cur, _cols, start, end, lt, utc):
@@ -163,10 +159,10 @@
         ary = numpy.array(cur.fetchall())
         if ary.shape[0] == 0:
             print('No data for ' + c.rowname)
-            return
+            continue
 
-        # Create TZ naive from POSIX stamp, then convert to TZ aware UTC then adjust to local time
-        c.xdata = map(lambda f: datetime.datetime.fromtimestamp(f).replace(tzinfo = utc).astimezone(lt), ary[:,0])
+        # Convert epoch stamp to datetime with UTC timezone
+        c.xdata = map(lambda f: datetime.datetime.utcfromtimestamp(f).replace(tzinfo = utc), ary[:,0])
         c.ydata = ary[:,1]
         if c.conv != None:
             c.ydata = map(c.conv, c.ydata)
@@ -188,6 +184,10 @@
         colouridx += 1
         ax.append(c)
 
+    if len(ax1lines) == 0 and len(ax2lines) == 0:
+        print('Nothing to plot')
+        return
+
     # Load the right backend for display or save
     if fname == None:
         import matplotlib.pylab
@@ -207,7 +207,7 @@
             ax1.set_ylim(line.limits[0], line.limits[1])
         if line.annotation != None:
             annotations.append(line.annotation)
-    ax1.legend(loc = 'upper left')
+    ax1.legend(loc = 'center left')
 
     if len(ax2lines) > 0:
         ax2 = ax1.twinx()
@@ -220,21 +220,24 @@
             if line.annotation != None:
                 annotations.append(line.annotation)
 
-        ax2.legend(loc = 'upper right')
+        ax2.legend(loc = 'center right')
 
     if len(annotations) > 0:
-        ax1.text(0.02, 0.5, reduce(lambda a, b: a + '\n' + b, annotations),
+        ax1.text(0.02, 0.3, reduce(lambda a, b: a + '\n' + b, annotations),
                     transform = ax1.transAxes, bbox = dict(facecolor = 'blue', alpha = 0.5),
                     ha = 'left', va = 'top')
     ndays = int(max(1, round(((end - start).total_seconds()) / 86400)))
+    once = False
     for ax in fig.get_axes():
-        if ndays > 1:
-            ax.set_title('%s to %s' % (start.strftime('%Y-%m-%d'), end.strftime('%Y-%m-%d')))
-        else:
-            ax.set_title('%s' % (start.strftime('%Y-%m-%d')))
-        ax.set_xlim([start, end])
-        ax.format_xdata = lambda d: matplotlib.dates.num2date(d).strftime('%d %b %H:%M')
+        if not once:
+            once = True
+            if ndays > 1:
+                ax.set_title('%s to %s' % (start.astimezone(lt).strftime('%Y-%m-%d'), end.astimezone(lt).strftime('%Y-%m-%d')))
+            else:
+                ax.set_title('%s' % (start.astimezone(lt).strftime('%Y-%m-%d')))
+        ax.set_xlim([start.astimezone(utc), end.astimezone(utc)])
         ax.xaxis.grid(True)
+        ax.xaxis.axis_date(lt)
         ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%d %b\n%H:%M'))
         ax.xaxis.set_major_locator(matplotlib.dates.HourLocator(interval = 2 * ndays))
         ax.xaxis.set_minor_locator(matplotlib.dates.MinuteLocator(interval = 5 * ndays))
@@ -250,50 +253,5 @@
         canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(fig) # Sets canvas in fig too
         fig.savefig(startdt.strftime(fname))
 
-def updatedb(cur, data):
-    mkdb(cur)
-    for d in data['reads']['data']:
-        ts = datetime.datetime.strptime(d['t_stamp'], '%Y-%m-%dT%H:%M:%SZ')
-        # Note we rename *energy* to *power* here to match what it actually means
-        vals = [ts, d['battery_charge'], d['battery_energy'], d['energy_consumed'], d['energy_expected'], d['energy_exported'], d['energy_generated'],
-                    d['energy_imported'], d['estimated_savings'], d['pv_forecast'], d['pv_generation']['battery_energy'],
-                    d['pv_generation']['grid_energy'], d['pv_generation']['site_energy'], d['site_consumption']['battery_energy'],
-                    d['site_consumption']['grid_energy'], d['site_consumption']['pv_energy']]
-        skip = True
-        for v in vals[1:]:
-            if v != None:
-                skip = False
-                break
-        if skip:
-            print('Skipping empty record at ' + str(ts))
-            continue
-        cur.execute('INSERT OR IGNORE INTO agl(t_stamp, battery_charge, battery_power, power_consumed, power_expected, power_exported, power_generated, power_imported, estimated_savings, pv_forecast, pv_gen_battery, pv_gen_grid, pv_gen_site, site_cons_battery, site_cons_grid, site_cons_pv) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', vals)
-
-def gettoken(username, password):
-    authblob = json.encoder.JSONEncoder().encode({'email' : username, 'password' : password})
-    reply = requests.request('POST', loginurl, data = authblob, headers = {'Content-Type' : 'application/json'})
-    if reply.status_code != 200:
-        return None
-    return json.decoder.JSONDecoder().decode(reply.content)['access_token']
-
-def getdata(token, startdate, enddate):
-    #print('getting ' + startdate.strftime('%Y-%m-%d'))
-    reply = requests.request('GET', dataurl, params = {
-        'startDate' :	startdate.strftime('%Y-%m-%d'),
-        'endDate' :		enddate.strftime('%Y-%m-%d'),
-        'granularity' :	'Minute',
-        'metrics' :		'read',
-        'units' :		'W',
-        }, headers = { 'Authorization' : 'Bearer ' + token})
-
-    if reply.status_code != 200:
-        return None
-
-    return json.decoder.JSONDecoder().decode(reply.content)
-
-def logout(token):
-    reply = requests.request('GET', logouturl, headers = { 'Authorization' : 'Bearer ' + token})
-    return reply.status_code == 200
-
 if __name__ == '__main__':
     main()