class TestListQuery(unittest.TestCase): def setUp(self): self.bw_client = Client() self.bw_client.setEntityFromFile(KEY_FILE) self.bw_client.overrideAutoChainTo(True) def tearDown(self): self.bw_client.close() def testListQuery(self): for planet, probe in PERSISTED_DATA.items(): po = PayloadObject((64, 0, 0, 0), None, probe) uri = BASE_URI + "/persisted/" + planet self.bw_client.publish(uri, payload_objects=(po, ), persist=True) results = self.bw_client.query(BASE_URI + "/persisted/+") self.assertEquals(len(results), len(PERSISTED_DATA)) probes = [result.payload_objects[0].content for result in results] self.assertTrue( all([probe in PERSISTED_DATA.values() for probe in probes])) children = self.bw_client.list(BASE_URI + "/persisted") self.assertEquals(len(children), len(PERSISTED_DATA)) planets = [child[child.rfind("/") + 1:] for child in children] self.assertTrue( all([planet in PERSISTED_DATA.keys() for planet in planets]))
class TestPubSubscribe(unittest.TestCase): def onMessage(self, message): self.assertTrue(len(message.payload_objects) > 0) msg_body = message.payload_objects[0].content self.assertIn(msg_body, MESSAGES) self.counter += 1 if self.counter == len(MESSAGES): self.semaphore.release() def setUp(self): self.counter = 0 self.semaphore = Semaphore(0) self.bw_client = Client() self.bw_client.setEntityFromFile(KEY_FILE) self.bw_client.overrideAutoChainTo(True) self.bw_client.subscribe(URI, self.onMessage) def tearDown(self): self.bw_client.close() def testPublishSubscribe(self): for msg in MESSAGES: po = PayloadObject((64, 0, 0, 0), None, msg) self.bw_client.publish(URI, payload_objects=(po,)) self.semaphore.acquire()
def setUp(self): self.counter = 0 self.semaphore = Semaphore(0) self.bw_client = Client() self.bw_client.setEntityFromFile(KEY_FILE) self.bw_client.overrideAutoChainTo(True) self.bw_client.subscribe(URI, self.onMessage)
class TestPubSubscribe(unittest.TestCase): def onMessage(self, message): self.assertTrue(len(message.payload_objects) > 0) msg_body = message.payload_objects[0].content self.assertIn(msg_body, MESSAGES) self.counter += 1 if self.counter == len(MESSAGES): self.semaphore.release() def setUp(self): self.counter = 0 self.semaphore = Semaphore(0) self.bw_client = Client() self.bw_client.setEntityFromFile(KEY_FILE) self.bw_client.overrideAutoChainTo(True) self.bw_client.subscribe(URI, self.onMessage) def tearDown(self): self.bw_client.close() def testPublishSubscribe(self): for msg in MESSAGES: po = PayloadObject((64, 0, 0, 0), None, msg) self.bw_client.publish(URI, payload_objects=(po, )) self.semaphore.acquire()
def __init__(self): self.bw_client = Client() self.bw_client.setEntityFromEnviron() self.bw_client.overrideAutoChainTo(True) self.hod_client = HodClient("xbos/hod", self.bw_client) self.priority = { "fan": 1, "kettle": 2, "student_office_tstat": 3, "microwave": 4, "sra_office_tstat": 5, "space_heater": 5, "fridge": 6, "evse": 7, "michaels_office_tstat": 8 } meter_q = """ SELECT ?uri FROM rfs WHERE { ?m rdf:type brick:Building_Electric_Meter . ?m bf:uri ?uri . }; """ self.building_meter = Meter( self.bw_client, self.hod_client.do_query(meter_q)['Rows'][0]['?uri']) self.tstats = { "student_office_tstat": Thermostat( self.bw_client, "rfs/devices/s.pelican/Student_Office/i.xbos.thermostat"), "sra_office_tstat": Thermostat(self.bw_client, "rfs/devices/s.pelican/SRA_Office/i.xbos.thermostat"), "michaels_office_tstat": Thermostat( self.bw_client, "rfs/devices/s.pelican/Michaels_Office/i.xbos.thermostat") } self.plugloads = { "fan": Plug(self.bw_client, "rfs/devices/fan/s.tplink.v0/0/i.xbos.plug"), "fridge": Plug(self.bw_client, "rfs/devices/refrigerator/s.tplink.v0/0/i.xbos.plug"), "space_heater": Plug(self.bw_client, "rfs/devices/heater/s.tplink.v0/0/i.xbos.plug"), "kettle": Plug(self.bw_client, "rfs/devices/boiler/s.tplink.v0/0/i.xbos.plug"), "microwave": Plug(self.bw_client, "rfs/devices/microwave/s.tplink.v0/0/i.xbos.plug") } self.evse = EVSE(self.bw_client, "rfs/devices/s.aerovironment/ParkingLot/i.xbos.evse") self.evse.set_current_limit(_MAX_EVSE_CURRENT)
def setUp(self): self.counter = 0 self.semaphore = Semaphore(0) self.bw_client = Client() self.bw_client.asyncSetEntityFromFile(KEY_FILE, self.onSetEntityResponse) self.bw_client.overrideAutoChainTo(True) self.semaphore.acquire()
class TestPubSubFailure(unittest.TestCase): def setUp(self): self.bw_client = Client() self.bw_client.setEntityFromFile(KEY_FILE) self.bw_client.overrideAutoChainTo(True) def tearDown(self): self.bw_client.close() def testQueryFailure(self): with self.assertRaises(RuntimeError): # Unit test key should not have permissions on this URI self.bw_client.query("jkolb/test") def testListFailure(self): with self.assertRaises(RuntimeError): # Unit test key should not have permissions on this URI self.bw_client.list("jkolb/test")
def __init__(self, url, client=None, timeout=20): if client is None: client = Client() client.vk = client.setEntityFromEnviron() client.overrideAutoChainTo(True) if not isinstance(client, Client): raise TypeError( "first argument must be bw2python.client.Client or None") self.c = client self.vk = client.vk self.url = url responses = self.c.query("{0}/*/s.hod/!meta/lastalive".format(url)) for resp in responses: # get the metadata records from the response md_records = filter( lambda po: po.type_dotted == ponames.PODFSMetadata, resp.payload_objects) # get timestamp field from the first metadata record last_seen_timestamp = msgpack.unpackb( md_records[0].content).get('ts') # get how long ago that was now = time.time() * 1e9 # nanoseconds # convert to microseconds and get the timedelta diff = timedelta(microseconds=(now - last_seen_timestamp) / 1e3) print "Saw [{0}] HodDB {1}".format(self.url, pretty_print_timedelta(diff)) if diff.total_seconds() > timeout: raise TimeoutException("HodDB at {0} is too old".format( self.url))
class TestPubSubFailure(unittest.TestCase): def onMessage(self, message): pass def setUp(self): self.bw_client = Client() self.bw_client.setEntityFromFile(KEY_FILE) self.bw_client.overrideAutoChainTo(True) def tearDown(self): self.bw_client.close() def testSubscribeFailure(self): with self.assertRaises(RuntimeError): # Unit test key should not have permissions on this URI self.bw_client.subscribe("jkolb/test", self.onMessage) def testPublishFailure(self): with self.assertRaises(RuntimeError): # Unit test key should not have permissions on this URI po = PayloadObject(ponames.PODFText, None, "Hello, World!") self.bw_client.publish("jkolb/test", payload_objects=(po,))
class TestPubSubFailure(unittest.TestCase): def onMessage(self, message): pass def setUp(self): self.bw_client = Client() self.bw_client.setEntityFromFile(KEY_FILE) self.bw_client.overrideAutoChainTo(True) def tearDown(self): self.bw_client.close() def testSubscribeFailure(self): with self.assertRaises(RuntimeError): # Unit test key should not have permissions on this URI self.bw_client.subscribe("jkolb/test", self.onMessage) def testPublishFailure(self): with self.assertRaises(RuntimeError): # Unit test key should not have permissions on this URI po = PayloadObject(ponames.PODFText, None, "Hello, World!") self.bw_client.publish("jkolb/test", payload_objects=(po, ))
def __init__(self, signal, slot, ssus): self.signal = signal self.slot = slot self.ssu_list = SSU_Link.create_ssu_list(ssus) self.bw_client = Client() self.bw_client.setEntityFromEnviron() self.bw_client.overrideAutoChainTo(True) self.last_received_schedule = { 'kwargs': { 'temperature': None, 'relative_humidity': None, 'heating_setpoint': None, 'cooling_setpoint': None, 'override': None, 'fan': None, 'mode': None, 'state': None, 'time': time.time() * 1e9 } }
class TestListQuery(unittest.TestCase): def setUp(self): self.bw_client = Client() self.bw_client.setEntityFromFile(KEY_FILE) self.bw_client.overrideAutoChainTo(True) def tearDown(self): self.bw_client.close() def testListQuery(self): for planet, probe in PERSISTED_DATA.items(): po = PayloadObject((64, 0, 0, 0), None, probe) uri = BASE_URI + "/persisted/" + planet self.bw_client.publish(uri, payload_objects=(po,), persist=True) results = self.bw_client.query(BASE_URI + "/persisted/+") self.assertEquals(len(results), len(PERSISTED_DATA)) probes = [result.payload_objects[0].content for result in results] self.assertTrue(all([probe in PERSISTED_DATA.values() for probe in probes])) children = self.bw_client.list(BASE_URI + "/persisted") self.assertEquals(len(children), len(PERSISTED_DATA)) planets = [child[child.rfind("/")+1:] for child in children] self.assertTrue(all([planet in PERSISTED_DATA.keys() for planet in planets]))
def __init__(self, client=None, archivers=None): """ Creates a BW2 Data client Arguments: [client]: if this is None, we use environment vars to configure a client automatically; else, we use the client provided [archivers]: this is a list of base archiver URIs. These can be found by running "pundat scan <namespace>" """ # bw2 client if client is None: client = Client() client.vk = client.setEntityFromEnviron() client.overrideAutoChainTo(True) if not isinstance(client, Client): raise TypeError( "first argument must be bw2python.client.Client or None") self.c = client self.vk = client.vk if archivers is None: archivers = ["ucberkeley"] # default archiver self.archivers = [] # scan for archiver liveness for archiver in archivers: responses = self.c.query( "{0}/*/s.giles/!meta/lastalive".format(archiver)) for resp in responses: # get the metadata records from the response md_records = filter( lambda po: po.type_dotted == ponames.PODFSMetadata, resp.payload_objects) # get timestamp field from the first metadata record last_seen_timestamp = msgpack.unpackb( md_records[0].content).get('ts') # get how long ago that was now = time.time() * 1e9 # nanoseconds # convert to microseconds and get the timedelta diff = timedelta(microseconds=(now - last_seen_timestamp) / 1e3) print "Saw [{0}] archiver {1}".format( archiver, pretty_print_timedelta(diff)) if diff.total_seconds() < 20: self.archivers.append(archiver) if len(self.archivers) == 0: self.archivers = archivers
def __init__(self, url, client=None, timeout=30): """ Creates an MDAL client. Arguments: [url]: the BOSSWAVE uri where mdal is hosted [client]: if this is None, we use environment vars to configure a client automatically; else, we use the client provided from bw2python """ if client is None: client = Client() client.vk = client.setEntityFromEnviron() client.overrideAutoChainTo(True) if not isinstance(client, Client): raise TypeError( "first argument must be bw2python.client.Client or None") self.c = client self.vk = client.vk self.url = url # check liveness responses = self.c.query("{0}/*/s.mdal/!meta/lastalive".format(url)) for resp in responses: # get the metadata records from the response md_records = filter( lambda po: po.type_dotted == ponames.PODFSMetadata, resp.payload_objects) # get timestamp field from the first metadata record last_seen_timestamp = msgpack.unpackb( md_records[0].content).get('ts') # get how long ago that was now = time.time() * 1e9 # nanoseconds # convert to microseconds and get the timedelta diff = timedelta(microseconds=(now - last_seen_timestamp) / 1e3) print "Saw [{0}] MDAL {1}".format(self.url, pretty_print_timedelta(diff)) if diff.total_seconds() > timeout: raise TimeoutException("MDAL at {0} is too old".format( self.url))
from bw2python import ponames from bw2python.bwtypes import PayloadObject from bw2python.client import Client import smap import msgpack import datetime import time bw_client = Client() bw_client.setEntityFromEnviron() bw_client.overrideAutoChainTo(True) thermostat = smap.IMT550C() def toHandle(bw_message): for po in bw_message.payload_objects: if po.type_dotted == (2, 1, 1, 0): to_process = msgpack.unpackb(po.content) print to_process thermostat.set_state(to_process) bw_client.subscribe('{0}/slot/state'.format(thermostat.uri), toHandle) while True: msg = thermostat.get_state() po = PayloadObject((2, 1, 1, 0), None, msgpack.packb(msg)) bw_client.publish('{0}/signal/info'.format(thermostat.uri), payload_objects=(po,), persist=True) time.sleep(thermostat.sample_rate) #RFC 3339 timestamp UTC d = datetime.datetime.utcnow() timestamp = {'ts': int(time.time()*1e9), 'val': d.isoformat('T')}
import sys import numpy as np import cv2 import requests import time import random import string from PIL import Image, ExifTags from bw2python import ponames from bw2python.bwtypes import PayloadObject from bw2python.client import Client #uuid bw_client = Client() bw_client.setEntityFromEnviron() bw_client.overrideAutoChainTo(True) SERVER_ADDR = "http://localhost:8080" RESULT_PASS = 0 RESULT_BAD_FORMAT = 1 RESULT_FAIL = 2 DEFAULT_CHANNEL = "scratch.ns/cellmate" IDENTITY_LENGTH = 10 def test_file(filename): obj_name = os.path.basename(filename).split(".")[0] img = Image.open(filename) width, height = img.size if height/width == 480/640:
from bw2python import ponames from bw2python.bwtypes import PayloadObject from bw2python.client import Client bw_client = Client() bw_client.setEntityFromEnviron() bw_client.overrideAutoChainTo(True) for i in range(10): msg = "{}: Hello, World!".format(i) po = PayloadObject(ponames.PODFText, None, msg) bw_client.publish("scratch.ns/demo", payload_objects=(po,))
def setUp(self): self.bw_client = Client() self.bw_client.setEntityFromFile(KEY_FILE) self.bw_client.overrideAutoChainTo(True)
class TestListQuery(unittest.TestCase): def onSetEntityResponse(self, response): self.assertEqual("okay", response.status) self.semaphore.release() def assertOkay(self, response): self.assertEqual("okay", response.status) def onMessage(self, message): if message.getFirstValue("finished") != "true": self.assertTrue(len(message.payload_objects) > 0) msg_body = message.payload_objects[0].content self.assertIn(msg_body, PERSISTED_DATA.values()) self.counter += 1 else: self.assertEqual(self.counter, len(PERSISTED_DATA)) self.semaphore.release() def onListResult(self, child): if child is not None: planet = child[child.rfind("/")+1:] self.assertIn(planet, PERSISTED_DATA.keys()) self.counter += 1 else: self.assertEqual(self.counter, len(PERSISTED_DATA)) self.semaphore.release() def setUp(self): self.counter = 0 self.semaphore = Semaphore(0) self.bw_client = Client() self.bw_client.asyncSetEntityFromFile(KEY_FILE, self.onSetEntityResponse) self.bw_client.overrideAutoChainTo(True) self.semaphore.acquire() def tearDown(self): self.bw_client.close() def testListQuery(self): for planet, probe in PERSISTED_DATA.items(): po = PayloadObject((64, 0, 0, 0), None, probe) uri = BASE_URI + "/persisted/" + planet self.bw_client.asyncPublish(uri, self.assertOkay, payload_objects=(po,), persist=True) self.bw_client.asyncQuery(BASE_URI + "/persisted/+", self.assertOkay, self.onMessage) self.semaphore.acquire() self.counter = 0 self.bw_client.asyncList(BASE_URI + "/persisted", self.assertOkay, self.onListResult) self.semaphore.acquire()
class TestListQuery(unittest.TestCase): def onSetEntityResponse(self, response): self.assertEqual("okay", response.status) self.semaphore.release() def assertOkay(self, response): self.assertEqual("okay", response.status) def onMessage(self, message): if message.getFirstValue("finished") != "true": self.assertTrue(len(message.payload_objects) > 0) msg_body = message.payload_objects[0].content self.assertIn(msg_body, PERSISTED_DATA.values()) self.counter += 1 else: self.assertEqual(self.counter, len(PERSISTED_DATA)) self.semaphore.release() def onListResult(self, child): if child is not None: planet = child[child.rfind("/") + 1:] self.assertIn(planet, PERSISTED_DATA.keys()) self.counter += 1 else: self.assertEqual(self.counter, len(PERSISTED_DATA)) self.semaphore.release() def setUp(self): self.counter = 0 self.semaphore = Semaphore(0) self.bw_client = Client() self.bw_client.asyncSetEntityFromFile(KEY_FILE, self.onSetEntityResponse) self.bw_client.overrideAutoChainTo(True) self.semaphore.acquire() def tearDown(self): self.bw_client.close() def testListQuery(self): for planet, probe in PERSISTED_DATA.items(): po = PayloadObject((64, 0, 0, 0), None, probe) uri = BASE_URI + "/persisted/" + planet self.bw_client.asyncPublish(uri, self.assertOkay, payload_objects=(po, ), persist=True) self.bw_client.asyncQuery(BASE_URI + "/persisted/+", self.assertOkay, self.onMessage) self.semaphore.acquire() self.counter = 0 self.bw_client.asyncList(BASE_URI + "/persisted", self.assertOkay, self.onListResult) self.semaphore.acquire()
import sys import numpy as np import cv2 import requests import time import random import string from PIL import Image, ExifTags from bw2python import ponames from bw2python.bwtypes import PayloadObject from bw2python.client import Client bw_client = Client() bw_client.setEntityFromEnviron() bw_client.overrideAutoChainTo(True) SERVER_ADDR = "http://localhost:8080" RESULT_PASS = 0 RESULT_BAD_FORMAT = 1 RESULT_FAIL = 2 DEFAULT_CHANNEL = "scratch.ns/cellmate" IDENTITY_LENGTH = 10 def test_file(filename): obj_name = os.path.basename(filename).split(".")[0] img = Image.open(filename) width, height = img.size
class Scheduler(object): def __init__(self, signal, slot, ssus): self.signal = signal self.slot = slot self.ssu_list = SSU_Link.create_ssu_list(ssus) self.bw_client = Client() self.bw_client.setEntityFromEnviron() self.bw_client.overrideAutoChainTo(True) self.last_received_schedule = { 'kwargs': { 'temperature': None, 'relative_humidity': None, 'heating_setpoint': None, 'cooling_setpoint': None, 'override': None, 'fan': None, 'mode': None, 'state': None, 'time': time.time() * 1e9 } } def run(self): print "scheduler running" self.bw_client.subscribe(self.slot, self.on_message) while True: #For time-based SSUs. Sends a signal every hour. Publishing will fail if initial SSU is not strictly time-based. msg = copy.deepcopy(self.last_received_schedule) msg['kwargs']['time'] = time.time() * 1e9 thread.start_new_thread(self.publish, (), msg) time.sleep(3600) print "sleeping" def publish(self, **kwargs): try: kwargs = kwargs.get('kwargs') sched = self.generate_schedule(kwargs.get('temperature'), kwargs.get('relative_humidity'), kwargs.get('heating_setpoint'), kwargs.get('cooling_setpoint'), kwargs.get('override'), kwargs.get('fan'), kwargs.get('mode'), kwargs.get('state'), kwargs.get('time')) self.publish_schedule(*sched) except Exception as e: print "Failed to publish message", e def generate_schedule(self, temp, rel_humidity, heating_setpt, cooling_setpt, override, fan, mode, state, time): data = (temp, rel_humidity, heating_setpt, cooling_setpt, override, fan, mode, state, time) curr = self.ssu_list while curr is not None: data = curr.ssu.generate_schedule(*data) curr = curr.rest heating_setpt, cooling_setpt = data[2], data[3] if temp <= heating_setpt: mode = 1 elif temp >= cooling_setpt: mode = 2 return float(heating_setpt), float(cooling_setpt), override, mode, fan def publish_schedule(self, heating_setpt, cooling_setpt, override, mode, fan): assert isinstance(heating_setpt, float) assert isinstance(cooling_setpt, float) assert isinstance(override, bool) assert isinstance(mode, int) assert isinstance(fan, bool) t = { 'heating_setpoint': heating_setpt, 'cooling_setpoint': cooling_setpt, 'override': override, 'mode': mode, 'fan': fan } po = PayloadObject((2, 1, 1, 0), None, msgpack.packb(t)) print t self.bw_client.publish(self.signal, payload_objects=(po, )) def on_message(self, bw_message): print "msg received" try: for po in bw_message.payload_objects: if po.type_dotted == (2, 1, 1, 0): tstat_data = msgpack.unpackb(po.content) self.last_received_schedule = {'kwargs': tstat_data} thread.start_new_thread(self.publish, (), self.last_received_schedule) except Exception as e: print e
except ValueError: print "Invalid parameter file" sys.exit(1) dest_uri = params.get("dest_uri") if dest_uri is None: print "No 'dest_uri' parameter specified" sys.exit(1) message = params.get("message") if message is None: print "No 'message' parameter specified" sys.exit(1) try: num_iters = int(sys.argv[1]) except ValueError: print "Invalid number of iterations specified" sys.exit(1) bw_client = Client() bw_client.setEntityFromEnviron() bw_client.overrideAutoChainTo(True) for i in range(num_iters): msg = "({}) {}".format(i, message) po = PayloadObject(ponames.PODFString, None, msg) bw_client.publish(dest_uri, payload_objects=(po,)) time.sleep(1) print "Emitted {} messages. Terminating".format(num_iters)
class Controller: def __init__(self): self.bw_client = Client() self.bw_client.setEntityFromEnviron() self.bw_client.overrideAutoChainTo(True) self.hod_client = HodClient("xbos/hod", self.bw_client) self.priority = { "fan": 1, "kettle": 2, "student_office_tstat": 3, "microwave": 4, "sra_office_tstat": 5, "space_heater": 5, "fridge": 6, "evse": 7, "michaels_office_tstat": 8 } meter_q = """ SELECT ?uri FROM rfs WHERE { ?m rdf:type brick:Building_Electric_Meter . ?m bf:uri ?uri . }; """ self.building_meter = Meter( self.bw_client, self.hod_client.do_query(meter_q)['Rows'][0]['?uri']) self.tstats = { "student_office_tstat": Thermostat( self.bw_client, "rfs/devices/s.pelican/Student_Office/i.xbos.thermostat"), "sra_office_tstat": Thermostat(self.bw_client, "rfs/devices/s.pelican/SRA_Office/i.xbos.thermostat"), "michaels_office_tstat": Thermostat( self.bw_client, "rfs/devices/s.pelican/Michaels_Office/i.xbos.thermostat") } self.plugloads = { "fan": Plug(self.bw_client, "rfs/devices/fan/s.tplink.v0/0/i.xbos.plug"), "fridge": Plug(self.bw_client, "rfs/devices/refrigerator/s.tplink.v0/0/i.xbos.plug"), "space_heater": Plug(self.bw_client, "rfs/devices/heater/s.tplink.v0/0/i.xbos.plug"), "kettle": Plug(self.bw_client, "rfs/devices/boiler/s.tplink.v0/0/i.xbos.plug"), "microwave": Plug(self.bw_client, "rfs/devices/microwave/s.tplink.v0/0/i.xbos.plug") } self.evse = EVSE(self.bw_client, "rfs/devices/s.aerovironment/ParkingLot/i.xbos.evse") self.evse.set_current_limit(_MAX_EVSE_CURRENT) def control(self, threshold): if self.evse.state: car_demand = self.evse.current * self.evse.voltage allowed_car_threshold = threshold - self.building_meter.power * 1000 if car_demand < allowed_car_threshold: if self.evse.current_limit < _MAX_EVSE_CURRENT: print( "current total consumption is less than threshold, increasing car charging limit" ) if allowed_car_threshold < _MAX_EVSE_CONSUMPTION: print("setting limit to:", (allowed_car_threshold) // _MAX_EVSE_VOLTAGE) self.evse.set_current_limit( (allowed_car_threshold) // _MAX_EVSE_VOLTAGE) else: print("setting limit to:", _MAX_EVSE_CURRENT) self.evse.set_current_limit(_MAX_EVSE_CURRENT) else: print( "current total consumption is less than threshold, evse limit is already at max nothing to do" ) return else: if self.building_meter.power <= threshold: print( "current building consumption is less than threshold and evse is off, nothing to do" ) return # current consumption is higher than threshold # get total power consumption of controllable loads without evse (plugloads and baseboard heaters) controllable_loads = 0 for _, tstat in self.tstats.iteritems(): controllable_loads += (tstat.state * _BASEBOARD_HEATER_CONSUMPTION) for _, plug in self.plugloads.iteritems(): controllable_loads += plug.power print("Building electric meter:", self.building_meter.power * 1000) print("Total controllable_loads power:", controllable_loads) process_load = self.building_meter.power * 1000 - controllable_loads print("Total process (uncontrollable) loads power:", process_load) # if process_load is greater than threshold if process_load >= threshold: if controllable_loads == 0: print( "current consumption is greater than threshold, but all controllable_loads are off, nothing to do" ) return else: print( "current consumption is greater than threshold, turning off all controllable loads. nothing else to do" ) for _, tstat in self.tstats.iteritems(): tstat.set_mode(0) for _, plug in self.plugloads.iteritems(): plug.set_state(0.0) self.evse.set_state(False) return # subtract uncontrollable loads from threshold ctrl_threshold = threshold - process_load print("Controllable threshold:", ctrl_threshold) # get and sort controllable_loads controllable_loads = [{ 'name': 'fan', 'priority': self.priority.get('fan'), 'capacity': self.plugloads.get('fan').power, 'state': int(self.plugloads.get('fan').state) }, { 'name': 'kettle', 'priority': self.priority.get('kettle'), 'capacity': self.plugloads.get('kettle').power, 'state': int(self.plugloads.get('kettle').state) }, { 'name': 'student_office_tstat', 'priority': self.priority.get('student_office_tstat'), 'capacity': _BASEBOARD_HEATER_CONSUMPTION, 'state': self.tstats.get('student_office_tstat').state }, { 'name': 'microwave', 'priority': self.priority.get('microwave'), 'capacity': self.plugloads.get('microwave').power, 'state': int(self.plugloads.get('microwave').state) }, { 'name': 'sra_office_tstat', 'priority': self.priority.get('sra_office_tstat'), 'capacity': _BASEBOARD_HEATER_CONSUMPTION, 'state': self.tstats.get('sra_office_tstat').state }, { 'name': 'space_heater', 'priority': self.priority.get('space_heater'), 'capacity': self.plugloads.get('space_heater').power, 'state': int(self.plugloads.get('space_heater').state) }, { 'name': 'michaels_office_tstat', 'priority': self.priority.get('michaels_office_tstat'), 'capacity': _BASEBOARD_HEATER_CONSUMPTION, 'state': self.tstats.get('michaels_office_tstat').state }, { 'name': 'fridge', 'priority': self.priority.get('fridge'), 'capacity': self.plugloads.get('fridge').power, 'state': int(self.plugloads.get('fridge').state) }, { 'name': 'evse', 'priority': self.priority.get('evse'), 'capacity': _MIN_EVSE_CONSUMPTION, 'state': int(self.evse.state) }] controllable_loads = sorted(controllable_loads, key=operator.itemgetter( 'priority', 'capacity'), reverse=True) loads_to_keep = [] # get loads to keep on for load in controllable_loads: if load['state'] == 1 and load['capacity'] <= ctrl_threshold: print load loads_to_keep.append(load['name']) ctrl_threshold -= load['capacity'] print("Updated controllable threshold:", ctrl_threshold) # turn off other loads for load in controllable_loads: if load['state'] == 1 and load['name'] not in loads_to_keep: if load['name'] == 'evse': print "turning off evse" self.evse.set_state(False) elif load['name'].endswith('_tstat'): print "turning off tstat: " + load['name'] self.tstats.get(load['name']).set_mode(0) else: print "turning off plug: " + load['name'] self.plugloads.get(load['name']).set_state(0.0) # set current_limit for evse to match threshold if ctrl_threshold > 0 and 'evse' in loads_to_keep: if _MIN_EVSE_CONSUMPTION + ctrl_threshold < _MAX_EVSE_CONSUMPTION: print("setting limit to:", (_MIN_EVSE_CONSUMPTION + ctrl_threshold) // _MAX_EVSE_VOLTAGE) self.evse.set_current_limit( (_MIN_EVSE_CONSUMPTION + ctrl_threshold) // _MAX_EVSE_VOLTAGE) else: print("setting limit to:", _MAX_EVSE_CURRENT) self.evse.set_current_limit(_MAX_EVSE_CURRENT) def report_state(self): print("EVSE state: ", self.evse.state) print("EVSE current: ", self.evse.current) print("EVSE voltage: ", self.evse.voltage) print("Building_Electric_Meter: ", self.building_meter.power * 1000) for _, tstat in self.tstats.iteritems(): print("Tstat ", tstat._uri, " State: ", tstat.state) print("Tstat ", tstat._uri, " Power: ", tstat.state * _BASEBOARD_HEATER_CONSUMPTION) for _, plug in self.plugloads.iteritems(): print("Plugload ", plug._uri, " State: ", plug.state) print("Plugload ", plug._uri, " Power: ", plug.power)