Exemple #1
0
class Recorder(Component):
    def __init__(self, logfile):
        super(Recorder, self).__init__()
        self.pid = os.getpid()
        self.logger.info("(PID %s) - starting Recorder", str(self.pid))

        self.connected = 0
        self.interval_trades = {}
        self.finalized = -1
        self.solutions = collections.defaultdict(dict)
        self.solution2solver = {}
        self.dbase = Database()

        logpath = '/tmp/' + logfile + '.log'
        try:
            os.remove(logpath)
        except OSError:
            pass
        self.fh = logging.FileHandler(logpath)
        self.fh.setLevel(logging.WARNING)
        self.fh.setFormatter(self.logformatter)
        self.logger.addHandler(self.fh)

        self.logger.warning("(PID %s) - starting Recorder", str(self.pid))

    def on_contractAddr(self):
        req = self.contractAddr.recv_pyobj()
        self.logger.info("PID (%s) - on_contractAddr():%s", str(self.pid),
                         str(req))

        self.epoch = time() - req['time']
        self.contract_address = req['contract']
        self.logger.info("Contract address: " + self.contract_address)
        self.logger.info("Setting up connection to Ethereum client...")
        client = EthereumClient(ip=MINER, port=PORT)
        self.account = client.accounts()[0]  # use the first owned address
        self.logger.info("Creating contract object...")
        self.contract = MatchingContract(client, self.contract_address)
        self.connected = 1

    def on_poller(self):
        now = self.poller.recv_pyobj()
        self.logger.info('PID(%s) - on_poller(): %s', str(self.pid), str(now))

        if self.connected == 0:
            self.query_contract_address()

        elif self.connected == 1:
            self.logger.debug("Polling events...")
            for event in self.contract.poll_events():
                params = event['params']
                name = event['name']
                self.logger.info("{}({}).".format(name, params))

                if name == "Finalized":
                    self.finalized = params['interval']
                    stopWatch = {
                        "interval": self.finalized,
                        "start": time(),
                        "running": 1
                    }
                    self.logger.info("interval finalized : {}".format(
                        self.finalized))
                    self.interval_trades[self.finalized] = []
                elif name == "TradeFinalized":
                    if (stopWatch["running"]):
                        stopWatch["running"] = 0
                        stopWatch["split"] = time() - stopWatch["start"]
                        self.dbase.log(self.finalized, "Solver",
                                       "FinalizeTime", stopWatch["split"])
                    interval = params['time']
                    power = params['power']
                    self.interval_trades[self.finalized].append(power)
                    self.logger.info(self.finalized)
                    self.logger.info(self.interval_trades[self.finalized])
                    self.dbase.log(self.finalized, "Solver",
                                   "TotalEnergyTraded",
                                   sum(self.interval_trades[self.finalized]))

                elif name == "TradeAdded":
                    interval = params['time']
                    ID = params['solutionID']
                    pwr = params['power']
                    solverID = self.solution2solver[ID]
                    if int(ID) < 10:
                        ID = "0" + str(ID)
                    if int(ID) < 100:
                        ID = "0" + str(ID)
                    try:
                        self.solutions[ID][interval] += pwr
                    except KeyError:
                        self.solutions[ID][interval] = pwr
                    #TradeAdded({'solutionID': 63, 'power': 400, 'time': 93, 'objective': 400, 'buyerID': 65, 'sellerID': 27}).
                    self.logger.info(
                        "TradeAdded : interval:{}, Solver:{}, SolutionID:{}, pwr:{}"
                        .format(interval, solverID, ID,
                                self.solutions[ID][interval]))
                    self.dbase.log(interval, "solution" + str(ID),
                                   "Solver" + str(solverID),
                                   self.solutions[ID][interval])
                    self.logger.info("{}({}).".format(name, params))
                elif (name == "SolutionCreated"):
                    solverID = params['solverID']
                    solutionID = params['solutionID']
                    self.solution2solver[solutionID] = solverID
                    self.logger.info(
                        "SolutionCreated Solver:{} Solution:{}".format(
                            solverID, solutionID))

    def handlePeerStateChange(self, state, uuid):
        self.logger.warning("peer %s is %s at: %s" % (uuid, state, time()))

    def __destroy__(self):
        self.logger.info("(PID %s) - stopping Recorder", str(self.pid))

    def query_contract_address(self):
        msg = {'request': "query_contract_address"}
        self.logger.info(msg)

        try:
            #self.cltReqPort.send_pyobj(msg)
            self.contractAddr.send_pyobj(msg)
        except PortError as e:
            self.logger.info("query_contract_address:send exception = %d" %
                             e.errno)
            if e.errno in (PortError.EAGAIN, PortError.EPROTO):
                self.logger.info("query_contract_address: try again")
Exemple #2
0
class Trader(Component):
    def __init__(self,ID,logfile):
        super(Trader, self).__init__()
        self.pid = os.getpid()
        self.logger.info("(PID %s) - starting Trader",str(self.pid))

        self.prosumer_id = ID
        self.net_production = self.read_data(self.prosumer_id)
        self.selling_offers = set()
        self.buying_offers = set()
        self.connected =0

        self.dbase = Database()

        self.role = None
        self.roleID = 0
        #self.grid = zmq.Context().socket(zmq.PUB)
        #self.grid.bind('tcp://127.0.0.1:2000')
        self.interval_asks = {}
        self.interval_bids = {}
        self.interval_trades ={}
        self.finalized = -1

        #RESOURCE MANAGEMENT PARAMETERS
        #NETWORK
        self.blk = 512
        self.min = 1*self.blk
        self.max = 4*self.blk
        self.msg_size = self.min


        logpath = '/tmp/' + logfile + '.log'
        self.killLog = 'killLog.log'
        try: os.remove(logpath)
        except OSError: pass
        self.fh = logging.FileHandler(logpath)
        self.fh.setLevel(logging.WARNING)
        self.fh.setFormatter(self.logformatter)
        self.logger.addHandler(self.fh)

        self.logger.warning("(PID %s) - starting Trader",str(self.pid))

    def on_contractAddr(self):
        try :
            req = self.contractAddr.recv_pyobj()
            if 'contract' in req:
                self.logger.info("PID (%s) - on_contractAddr():%s",str(self.pid),str(req))
                self.epoch = time() - req['time']
                self.time_interval = int(time() - self.epoch) // INTERVAL_LENGTH
                self.contract_address = req['contract']
                self.logger.info("Contract address: " + self.contract_address)
                self.logger.info("Setting up connection to Ethereum client...")
                client = EthereumClient(ip=MINER, port=PORT)
                self.account = client.accounts()[0] # use the first owned address
                self.logger.info("Creating contract object...")
                self.contract = MatchingContract(client, self.contract_address)
                self.contract.registerProsumer(self.account, prosumer_id, PROSUMER_FEEDER[prosumer_id])
                self.connected = 1
                self.logger.warning("Connected: %s" %self.connected)
            else :
                self.logger.info("reply is:%s " %req)
        except PortError as e:
            self.logger.info("on_contractAddr:port exception = %d" % e.errno)
            if e.errno in (PortError.EAGAIN,PortError.EPROTO):
                self.logger.info("on_contractAdd: port error received")


    def on_poller(self):
        now = self.poller.recv_pyobj()
        self.logger.info('PID(%s) - on_poller(): %s',str(self.pid),str(now))

        if self.connected == 0 :
            self.query_contract_address()
        elif self.connected == 1 :
            self.logger.debug("Polling events...")


            # if self.time_interval == 28 and self.prosumer_id == 106:
            #     with open(self.killLog, 'a') as f:
            #         f.write("KILL PROCESS: %s" %time())
            #     self.logger.warning("KILL PROCESS: %s" %time())
            #     os.kill(self.pid,signal.SIGKILL)


            events = self.contract.poll_events()
#             try:# added this because laptop lost connection, and would need to reconnect to miner and grafana
#                 events = self.contract.poll_events()
#             except Exception as e:
#                 self.logger.warning("LOST CONNECTION TO HOST: %s" %e)
#                 self.connected =0


            for event in events: #self.contract.poll_events():
                params = event['params']
                name = event['name']
                if (name == "BuyingOfferPosted") and (params['prosumer'] == self.prosumer_id):
                    self.buying_offers.add(params['ID'])
                    self.logger.info("{}({}).".format(name, params))
                elif (name == "SellingOfferPosted") and (params['prosumer'] == self.prosumer_id):
                    self.selling_offers.add(params['ID'])
                    self.logger.info("{}({}).".format(name, params))
                elif (name == "TradeAdded") and ((params['sellerID'] in self.selling_offers) or (params['buyerID'] in self.buying_offers)):
                    self.logger.info("{}({}).".format(name, params))
                elif name == "Finalized":
                    self.finalized = params['interval']
                    self.logger.info("interval finalized : {}".format(self.finalized))
                    self.interval_trades[self.finalized] = [] #List of trades finalized for a given interval
                    self.time_interval = self.finalized + 1
                    self.logger.info("time_interval: %s = finalized: %s + 1" %(self.time_interval, self.finalized))
                    self.dbase.log(self.finalized-2, "interval_now", self.prosumer_id, self.finalized-2)
                    self.dbase.log(self.time_interval, self.prosumer_id, self.role, 0)



                elif (name == "TradeFinalized") and ((params['sellerID'] in self.selling_offers) or (params['buyerID'] in self.buying_offers)):
                    self.logger.warning("{}({}).".format(name, params))
                    time_interval = params['time']
                    power = params['power']
                    self.interval_trades[time_interval].append(power)
                    #self.grid.send_pyobj({"interval" : self.finalized, "power": self.roleID*sum(self.interval_trades[self.finalized]), "INTERVAL_LENGTH" : INTERVAL_LENGTH, "time_stamp" : next_actuation})
                    self.dbase.log(time_interval, self.prosumer_id, self.role, sum(self.interval_trades[time_interval]))

                    self.ack.send_pyobj("%s" %(self.prosumer_id)) #Time Sensitive Messaging
            # self.waste_network()


    def on_post(self):
        now = self.post.recv_pyobj()
        self.logger.info('PID(%s) - on_post(): %s',str(self.pid),str(now))
        if self.connected :
            self.post_offers(self.time_interval)

    def handleActivate(self):
        with open(self.killLog, 'a') as f:
            f.write("Live: %s" %time())
        self.logger.warning("handleActivate: %s" %time())
        self.logger.warning("UUID: %s" %self.getUUID())
#         self.cltReqPort.set_recv_timeout(1.0)
#         self.cltReqPort.set_send_timeout(1.0)
#         rto = self.cltReqPort.get_recv_timeout()
#         sto = self.cltReqPort.get_send_timeout()
#         self.logger.info("handleActivate: (rto,sto) = (%s,%s)" % (str(rto),str(sto)))

    def handlePeerStateChange(self,state,uuid):
        self.logger.warning("UUID: %s, STATE: %s" %(uuid, state))

    def handleNICStateChange(self, state):
        if state=="down":
            self.logger.warning("UUID: %s" %self.getUUID())
            self.logger.warning("NIC is %s" % state)
            self.connected = 0
            self.logger.warning("Connected: %s" %self.connected)
        elif state =="up":
            self.logger.warning("NIC is %s" % state)
#             self.connectGrafana()#This appears to be unnecessary...
#

    def __destroy__(self):
        self.logger.info("(PID %s) - stopping Trader",str(self.pid))


    def query_contract_address(self):
        msg = {
            'request': "query_contract_address"
        }
        self.logger.info(msg)

        try:
            #self.cltReqPort.send_pyobj(msg)
            self.contractAddr.send_pyobj(msg)
        except PortError as e:
            self.logger.info("query_contract_address:send exception = %d" % e.errno)
            if e.errno in (PortError.EAGAIN,PortError.EPROTO):
                self.logger.info("query_contract_address: try again")


    def post_offers(self, time_interval):
        remaining_offers = []
        self.logger.info("Posting offers for interval {}...".format(time_interval))
        for offer in self.net_production:
            self.logger.info("energy: %s" %(offer['energy']))
            if offer['end'] < time_interval: # offer in the past, discard it
                pass
            elif offer['start'] <= time_interval + PREDICTION_WINDOW: # offer in near future, post it
                if offer['energy'] < 0:
                    self.role = "consumer"
                    self.roleID = -1
                    self.logger.info("postBuyingOffer({}, {}, {}, {})".format(self.prosumer_id, offer['start'], offer['end'], -offer['energy']))
                    self.contract.postBuyingOffer(self.account, self.prosumer_id, offer['start'], offer['end'], -offer['energy'])
                    try:
                        self.interval_bids[offer['start']].append(offer['energy'])
                    except KeyError:
                        self.interval_bids[offer['start']] = [offer['energy']]
                    self.dbase.log(offer['start'], self.prosumer_id, "buying", sum(self.interval_bids[offer['start']]))
                else:
                    self.role = "producer"
                    self.roleID = 1
                    self.logger.info("postSellingOffer({}, {}, {}, {})".format(self.prosumer_id, offer['start'], offer['end'], offer['energy']))
                    self.contract.postSellingOffer(self.account, self.prosumer_id, offer['start'], offer['end'], offer['energy'])
                    try:
                        self.interval_asks[offer['start']].append(offer['energy'])
                    except KeyError:
                        self.interval_asks[offer['start']] = [offer['energy']]
                    self.dbase.log(offer['start'], self.prosumer_id, "selling", sum(self.interval_asks[offer['start']]))
            else: # offer in far future, post it later
                remaining_offers.append(offer)
            self.net_production = remaining_offers
            self.logger.info("Offers posted.")

    def read_data(self, prosumer_id):
        self.logger.info("Reading net production values...")
        feeder = int(prosumer_id / 100)
        prosumer = prosumer_id % 100
        print(os.getcwd())
        with open(DATA_PATH + "prosumer_{}.csv".format(prosumer_id), "rt") as fin:
            line = next(fin)
            data = []
            for line in fin:
                try:
                    fields = line.split(',')
                    data.append({
                        'start': int(fields[0]),
                        'end': int(fields[1]),
                        'energy': int(1000 * float(fields[2]))
                        })
                except Exception:
                    pass
            if not len(data):
                raise Exception("No values found in data file!")
            self.logger.info("Read {} values.".format(len(data)))
            return data

    def handleCPULimit(self):
        self.logger.info('handleCPULimit()')

    def handleMemLimit(self):
        self.logger.info('handleMemLimit()' )

    def handleNetLimit(self):
        self.logger.info('handleNetLimit %s' %self.msg_size)
        self.msg_size = self.min
        self.logger.info('handled NetLimit %s' %self.msg_size)
        now = datetime.datetime.now()
        self.dbase.post(now=now, tag_dict={"resource":"Network", "ID":self.prosumer_id}, seriesName="Waste", value=self.msg_size)

    def waste_network(self):
        msg = {
            'request': "waste",
            'payload': bytearray(self.msg_size)
        }
        self.logger.info("WASTE NETWORK")
        try:
            self.contractAddr.send_pyobj(msg)
            self.msg_size = self.msg_size + self.blk
#             if self.msg_size == self.max: self.msg_size = self.min
            now = datetime.datetime.now()
            self.dbase.post(now=now, tag_dict={"resource":"Network", "ID":self.prosumer_id}, seriesName="Waste", value=self.msg_size)
        except PortError as e:
            self.logger.info("waste_network:send exception = %d" % e.errno)
            if e.errno in (PortError.EAGAIN,PortError.EPROTO):
                self.logger.info("waste_network: try again")