Merge pull request #5 from evanrich/python3

Migrate to Python3 and add pricing info
This commit is contained in:
2018-09-10 11:53:16 -07:00
committed by GitHub
13 changed files with 45 additions and 31 deletions

View File

@@ -1,14 +1,14 @@
FROM python:2.7.15-alpine3.8 FROM python:3.7.0-alpine3.8
LABEL maintainer="Evan Richardson" LABEL maintainer="Evan Richardson"
LABEL version="1.0" LABEL version="1.1"
WORKDIR /app WORKDIR /app
COPY . /app COPY . /app
ENV PYTHONPATH=/app/src/python ENV PYTHONPATH=/app/src/python
RUN pip install --upgrade pip RUN pip3 install --upgrade pip
RUN pip install -r requirements.txt RUN pip3 install -r requirements.txt
RUN rm -rf /var/cache/apk #RUN rm -rf /var/cache/apk
CMD ["/app/src/bin/tHome-eagle.py", "-c", "/app/src/conf"] CMD ["/app/src/bin/tHome-eagle.py", "-c", "/app/src/conf"]

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
#=========================================================================== #===========================================================================
# #
@@ -17,9 +17,9 @@ messages.
""" """
import argparse import argparse
import bottle as B
import sys import sys
import json import json
import bottle as B
import tHome as T import tHome as T
#=========================================================================== #===========================================================================
@@ -41,6 +41,15 @@ def instant( client, data, cfg ):
return ( cfg.mqttPower, msg ) return ( cfg.mqttPower, msg )
#===========================================================================
def price( client, data, cfg ):
msg = {
"time" : data.TimeUnix,
"price" : data.Price,
"tier" : data.Tier,
}
return ( cfg.mqttPrice, msg )
#=========================================================================== #===========================================================================
handlers = { handlers = {
#"BlockPriceDetail" : #"BlockPriceDetail" :
@@ -51,7 +60,7 @@ handlers = {
#"MessageCluster" : #"MessageCluster" :
#"MeterInfo" : #"MeterInfo" :
#"NetworkInfo" : #"NetworkInfo" :
#"PriceCluster" : "PriceCluster" : price,
#"Reading" : #"Reading" :
#"ScheduleInfo" : #"ScheduleInfo" :
#"TimeCluster" : #"TimeCluster" :

View File

@@ -6,7 +6,7 @@ import os
# #
#=========================================================================== #===========================================================================
host = os.getenv('MQTT_BROKER_IP', '192.168.1.20') host = os.getenv('MQTT_BROKER_IP', '192.168.1.20')
port = os.getenv('MQTT_BROKER_PORT', 1883) port = os.getenv('MQTT_BROKER_PORT', 31333)
# Keep alive time in seconds. Client sends a ping if no other message # Keep alive time in seconds. Client sends a ping if no other message
# is sent in this interval. # is sent in this interval.

View File

@@ -17,6 +17,12 @@ mqttEnergy = 'power/elec/Home/energy'
# Instantaneous power usage topic (reports power usage in W) # Instantaneous power usage topic (reports power usage in W)
mqttPower = 'power/elec/Home/power' mqttPower = 'power/elec/Home/power'
#Current price topic (returns current price of electricity from meter)
mqttPrice = 'power/elec/Home/price'
#Current rate label (returns rate label from meter)
mqttRateLabel = 'power/elec/Home/ratelabel'
#=========================================================================== #===========================================================================
# #
# Logging configuration. Env variables are allowed in the file name. # Logging configuration. Env variables are allowed in the file name.

View File

@@ -3,4 +3,4 @@
import tHome as T import tHome as T
d = T.config.parse( "/home/ted/proj/tHome/conf" ) d = T.config.parse( "/home/ted/proj/tHome/conf" )
print d print(d)

View File

@@ -1,5 +1,5 @@
#============================================================================= #=============================================================================
import StringIO import io
#============================================================================= #=============================================================================
class Data: class Data:
@@ -11,7 +11,7 @@ class Data:
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
def keys( self ): def keys( self ):
return self.__dict__.keys() return list(self.__dict__.keys())
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
def update( self, rhs ): def update( self, rhs ):
@@ -43,7 +43,7 @@ class Data:
def _formatValue( self, value, out, indent ): def _formatValue( self, value, out, indent ):
if isinstance( value, Data ): if isinstance( value, Data ):
out.write( "%s(\n" % self.__class__.__name__ ) out.write( "%s(\n" % self.__class__.__name__ )
for k, v in sorted( value.__dict__.iteritems() ): for k, v in sorted( value.__dict__.items() ):
if k[0] == "_": if k[0] == "_":
continue continue
@@ -56,7 +56,7 @@ class Data:
elif isinstance( value, dict ): elif isinstance( value, dict ):
out.write( "{\n" ) out.write( "{\n" )
for k, v in sorted( value.iteritems() ): for k, v in sorted( value.items() ):
if k[0] == "_": if k[0] == "_":
continue continue

View File

@@ -24,7 +24,7 @@ class Error ( Exception ):
exception.add( msg ) exception.add( msg )
raise exception, None, trace raise exception.with_traceback(trace)
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
@staticmethod @staticmethod
@@ -34,7 +34,7 @@ class Error ( Exception ):
newError = Error( str( exception ) ) newError = Error( str( exception ) )
newError.add( msg ) newError.add( msg )
raise newError, None, trace raise newError.with_traceback(trace)
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
def __init__( self, msg ): def __init__( self, msg ):

View File

@@ -21,7 +21,7 @@ def fimport( filePath ):
# Create a new module and exec the code in it's context. # Create a new module and exec the code in it's context.
m = imp.new_module( rootName ) m = imp.new_module( rootName )
m.__file__ = absPath m.__file__ = absPath
exec code in m.__dict__ exec(code, m.__dict__)
# Return the module object. # Return the module object.
return m return m

View File

@@ -3,7 +3,7 @@
# Dump hex bytes to a table. # Dump hex bytes to a table.
# #
#=========================================================================== #===========================================================================
import StringIO import io
#=========================================================================== #===========================================================================
def dump( buf ): def dump( buf ):

View File

@@ -33,7 +33,7 @@ def loads( text ):
#============================================================================= #=============================================================================
def _toStr( data, ignoreDicts=False ): def _toStr( data, ignoreDicts=False ):
# Convert unicode to string. # Convert unicode to string.
if isinstance( data, unicode ): if isinstance( data, str ):
return data.encode( 'utf-8' ) return data.encode( 'utf-8' )
# For lists, process each item. # For lists, process each item.
@@ -45,7 +45,7 @@ def _toStr( data, ignoreDicts=False ):
if isinstance( data, dict ) and not ignoreDicts: if isinstance( data, dict ) and not ignoreDicts:
return { return {
_toStr( k, ignoreDicts=True ) : _toStr( v, ignoreDicts=True ) _toStr( k, ignoreDicts=True ) : _toStr( v, ignoreDicts=True )
for k, v in data.iteritems() for k, v in data.items()
} }
# Otherwise return the original object. # Otherwise return the original object.

View File

@@ -138,7 +138,7 @@ class Poll:
# themselves. So make a copy of the dict value list list # themselves. So make a copy of the dict value list list
# containing all the objects so we're not modifying the client # containing all the objects so we're not modifying the client
# dictionary as we loop over it. # dictionary as we loop over it.
clients = self.clients.values()[:] clients = list(self.clients.values())[:]
for c in clients: for c in clients:
c.close() c.close()
@@ -169,7 +169,7 @@ class Poll:
# Returns tuple (fileDescriptor, bitFlag) of the files # Returns tuple (fileDescriptor, bitFlag) of the files
# that can act. # that can act.
events = self.poll.poll( timeOut_msec ) events = self.poll.poll( timeOut_msec )
except select.error, v: except select.error as v:
# Not sure why, but sometimes with a timeout value, you can # Not sure why, but sometimes with a timeout value, you can
# get an "interrupted system call" error thrown. Web # get an "interrupted system call" error thrown. Web
# searches indicate this isn't really an error and should be # searches indicate this isn't really an error and should be

View File

@@ -2,18 +2,18 @@
from tHome.util import Data from tHome.util import Data
d = Data( a=1, b="asdf", c=2 ) d = Data( a=1, b="asdf", c=2 )
print d print(d)
print "----" print("----")
d = Data( a=1, b="asdf", c=[2,3,4] ) d = Data( a=1, b="asdf", c=[2,3,4] )
print d print(d)
print "----" print("----")
d = Data( a=1, b="asdf", c={'a':3, 'b':4} ) d = Data( a=1, b="asdf", c={'a':3, 'b':4} )
print d print(d)
print "----" print("----")
d = Data( a=1, b=[ Data(a=1,b=2) ], c={'a':3, 'b':[1,2,3]} ) d = Data( a=1, b=[ Data(a=1,b=2) ], c={'a':3, 'b':[1,2,3]} )
print d print(d)
print "----" print("----")

View File

@@ -1,6 +1,5 @@
## TODO ## TODO
1. Need to add variables for username/password, in case anyone is using authentication with their broker 1. Need to add variables for username/password, in case anyone is using authentication with their broker
1. Need to try and port original code to Python 3.x
1. Make sure Dockerhub is set up to build when I want it to 1. Make sure Dockerhub is set up to build when I want it to
1. Look for ways to optimize the Dockerfile to reduce image size 1. Look for ways to optimize the Dockerfile to reduce image size
1. Try to get more stats from the Eagle ($/kWh from the meter, etc.) 1. Try to get more stats from the Eagle ($/kWh from the meter, etc.)