Ejemplo n.º 1
0
class TSMrecv(Component):
    def __init__(self, logfile):
        super(TSMrecv, self).__init__()
        self.pid = os.getpid()
        self.logger.info("(PID %s) - starting TSM receiver",str(self.pid))

        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 TSM receiver",str(self.pid))

    def on_ack(self):
        '''Time Sensitive Messaging '''
        msg = self.ack.recv_pyobj()
        self.logger.info("PID (%s) - on_ack():%s",str(self.pid),str(msg))
        sendTime = self.ack.get_sendTime()
        recvTime = self.ack.get_recvTime()
        self.logger.warning("sendTime: %s, recvTime: %s" %(sendTime, recvTime))
        self.logger.warning("%s FlightTime: %s" %(msg, recvTime-sendTime))
        self.dbase.post(now=datetime.datetime.now(), tag_dict={"ID":msg}, seriesName="TSM", value=recvTime-sendTime)

    def __destroy__(self):
        self.logger.info("(PID %s) - stopping TSM reciever",str(self.pid))
Ejemplo n.º 2
0
    def __init__(self, logfile):
        super(Solver, self).__init__()
        self.pid = os.getpid()

        self.logger.info("(PID %s) - starting Solver", str(self.pid))

        #Waste Space parameters
        self.delta = 1  # 1 MB #
        self.size = self.delta
        self.name = '/tmp/tmp%s' % randomword(8)
        self.logger.info(os.getcwd())

        #App Specific parameters
        self.solverID = 1
        print("solverID %s" % self.solverID)
        self.solution = None
        self.objective = 0
        self.connected = 0
        self.new_offers = False
        self.solver = MatchingSolver(MICROGRID)
        self.buying_offers = []
        self.selling_offers = []
        self.finalized = -1
        self.waiting_solutionID = False
        self.PREDICTION_WINDOW = 5
        self.recordTime = False
        self.interval_trades = {}
        self.solutions = {}
        self.ISID = 0
        self.DeadLine = 0.5  #seconds ideally this would be gotten from the framework API
        self.Pgain = 25  #50
        self.PWMax = 50
        self.priorPW = self.PREDICTION_WINDOW

        self.logpath = '/tmp/' + logfile + '.log'
        self.killLog = 'killLog.log'
        try:
            os.remove(self.logpath)
        except OSError:
            pass
        self.fh = logging.FileHandler(self.logpath)
        self.fh.setLevel(logging.INFO)
        self.fh.setFormatter(self.logformatter)
        self.logger.addHandler(self.fh)
        self.logger.info("(PID %s) - starting Solver", str(self.pid))
        self.s = open('/dev/zero').read(1024 * 100 - 1)

        self.dbase = Database()
        self.dbase.post(now=datetime.datetime.now(),
                        tag_dict={"object": "Solver_" + str(self.solverID)},
                        seriesName="PWMax",
                        value=self.PWMax)

        self.uid = os.geteuid()
        #         self.logger.info("UID: %s" %self.uid)
        self.username = pwd.getpwuid(self.uid)[0]
        #         self.logger.info("USERNAME: %s" %self.username)

        self.thisProcess = psutil.Process(self.pid)
        self.cpuUtil = self.thisProcess.cpu_percent()
Ejemplo n.º 3
0
    def __init__(self, logfile):
        super(TSMrecv, self).__init__()
        self.pid = os.getpid()
        self.logger.info("(PID %s) - starting TSM receiver",str(self.pid))

        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 TSM receiver",str(self.pid))
Ejemplo n.º 4
0
    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))
Ejemplo n.º 5
0
    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))
Ejemplo n.º 6
0
    def __init__(self, logfile):
        super(DSO, self).__init__()
        self.pid = os.getpid()
        self.logger.info("(PID %s) - starting DSO",str(self.pid))
        self.client = EthereumClient(ip=MINER, port=PORT)
        self.account = self.client.accounts()[0] # use the first owned address
        self.deploy_contract()
        self.next_interval = START_INTERVAL
        t = time()
        self.epoch = t - START_INTERVAL * INTERVAL_LENGTH

        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 DSO",str(self.pid))
Ejemplo n.º 7
0
class Solver(Component):
    def __init__(self, logfile):
        super(Solver, self).__init__()
        self.pid = os.getpid()

        self.logger.info("(PID %s) - starting Solver", str(self.pid))

        #Waste Space parameters
        self.delta = 1  # 1 MB #
        self.size = self.delta
        self.name = '/tmp/tmp%s' % randomword(8)
        self.logger.info(os.getcwd())

        #App Specific parameters
        self.solverID = 1
        print("solverID %s" % self.solverID)
        self.solution = None
        self.objective = 0
        self.connected = 0
        self.new_offers = False
        self.solver = MatchingSolver(MICROGRID)
        self.buying_offers = []
        self.selling_offers = []
        self.finalized = -1
        self.waiting_solutionID = False
        self.PREDICTION_WINDOW = 5
        self.recordTime = False
        self.interval_trades = {}
        self.solutions = {}
        self.ISID = 0
        self.DeadLine = 0.5  #seconds ideally this would be gotten from the framework API
        self.Pgain = 25  #50
        self.PWMax = 50
        self.priorPW = self.PREDICTION_WINDOW

        self.logpath = '/tmp/' + logfile + '.log'
        self.killLog = 'killLog.log'
        try:
            os.remove(self.logpath)
        except OSError:
            pass
        self.fh = logging.FileHandler(self.logpath)
        self.fh.setLevel(logging.INFO)
        self.fh.setFormatter(self.logformatter)
        self.logger.addHandler(self.fh)
        self.logger.info("(PID %s) - starting Solver", str(self.pid))
        self.s = open('/dev/zero').read(1024 * 100 - 1)

        self.dbase = Database()
        self.dbase.post(now=datetime.datetime.now(),
                        tag_dict={"object": "Solver_" + str(self.solverID)},
                        seriesName="PWMax",
                        value=self.PWMax)

        self.uid = os.geteuid()
        #         self.logger.info("UID: %s" %self.uid)
        self.username = pwd.getpwuid(self.uid)[0]
        #         self.logger.info("USERNAME: %s" %self.username)

        self.thisProcess = psutil.Process(self.pid)
        self.cpuUtil = self.thisProcess.cpu_percent()

    # def connectGrafana(self):
    #     try :
    #         # self.db = InfluxDBClient(Config.INFLUX_DBASE_HOST,Config.INFLUX_DBASE_PORT,
    #         #                          Config.INFLUX_DBASE_USER,Config.INFLUX_DBASE_PASSWORD,
    #         #                          "solverDbase")
    #         # self.db.create_database(Config.INFLUX_DBASE_NAME)
    #         # self.db.switch_database(Config.INFLUX_DBASE_NAME)
    #         self.dbase = Database()
    #         self.dbase.post(now=datetime.datetime.now(), tag_dict={"object":"Solver_"+str(self.solverID)}, seriesName="PWMax", value=self.PWMax)
    #
    #     except requests.exceptions.ConnectionError as e:
    #         self.logger.warning("CONNECTION ERROR %s" %e)
    #         self.logger.warning("try again")
    #         self.connectGrafana()

#     def on_contractAddr(self):
#         self.logger.info("on_contractAddr()")
#
#         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_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.solutions[self.time_interval] = {}

                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

            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))
        self.logger.info('update')

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

        elif self.connected == 1:
            self.logger.debug("Polling events...")
            #
            # if self.time_interval == 28:
            #     with open(self.killLog, 'w') as f:
            #         f.write("KILL PROCESS: %s" %time())
            #     self.logger.warning("KILL PROCESS: %s" %time())
            #     os.kill(self.pid,signal.SIGKILL)

            for event in self.contract.poll_events():
                params = event['params']
                name = event['name']
                self.logger.info("{}({}).".format(name, params))

                if (name == "BuyingOfferPosted") or (name
                                                     == "SellingOfferPosted"):
                    self.new_offers = True
                    offer = Offer(params['ID'], params['prosumer'],
                                  params['startTime'], params['endTime'],
                                  params['energy'])
                    if name == "BuyingOfferPosted":
                        self.buying_offers.append(offer)
                    else:
                        self.selling_offers.append(offer)
                elif (name == "SolutionCreated") and (params['solverID']
                                                      == self.solverID):

                    self.waiting_solutionID = False
                    solutionID = params['solutionID']

                    self.solutions[self.time_interval][self.ISID] = solutionID

                    if self.solution is not None:
                        self.logger.info(
                            "Solution {} created by contract, adding trades..."
                            .format(solutionID))
                        trades = [
                            trade for trade in self.solution
                            if int(trade['p']) > 0
                        ]
                        for trade in trades:
                            self.contract.addTrade(self.account, solutionID,
                                                   trade['s'].ID,
                                                   trade['b'].ID, trade['t'],
                                                   int(trade['p']))
                        self.logger.info(
                            "{} trades have been submitted to the contract.".
                            format(len(trades)))

#                         if self.PREDICTION_WINDOW < 60:
#                             self.PREDICTION_WINDOW +=5
#                         self.logger.info("PREDICTION_WINDOW: %s" %self.PREDICTION_WINDOW)
#                         self.dbase.post(now=datetime.datetime.now(), tag_dict={"resource":"Memory", "ID":'Solver'+str(self.solverID)}, seriesName="Waste", value=self.PREDICTION_WINDOW)

                    else:
                        self.logger.info(
                            "Solution {} created by contract, but no solution has been found for this time interval (yet)."
                            .format(solutionID))
                elif name == "Finalized":

                    self.logger.info("INTERVAL:%s SOLUTIONS: %s" %
                                     (self.time_interval,
                                      self.solutions[self.time_interval]))

                    self.finalized = params['interval']
                    self.time_interval = self.finalized + 1
                    self.objective = float("-inf")
                    self.solution = None

                    self.solutions[self.time_interval] = {}

                    if self.waiting_solutionID:
                        self.logger.error(
                            "INTERVAL FINALIZED BEFORE SOLUTION WAS CREATED, AND TRADES ADDED"
                        )
                        self.waiting_solutionID = False
                    # new_offers = False # TODO: offers for next interval might be added in the same block as the finalization for the previous!
                    self.logger.info(
                        "Trades for interval {} are now final, matching will consider only later intervals from now on."
                        .format(self.finalized))
                    self.logger.info("New interval is : {}".format(
                        self.time_interval))

                elif name == "TradeFinalized":
                    self.logger.info("{}({}).".format(name, params))
                    for offer in self.selling_offers:
                        if offer.ID == params['sellerID']:
                            offer.energy -= params['power']
                            break
                    for offer in self.buying_offers:
                        if offer.ID == params['buyerID']:
                            offer.energy -= params['power']
                            break

                elif name == "TradeAdded":
                    self.logger.info("{}({}).".format(name, params))

#         bashCommand = 'quota -w %s | awk "NR==3"' %self.uid # returns row
# #             self.logger.info("bashCommand: %s" %bashCommand)
#         p1 = subprocess.Popen(bashCommand, shell=True, stdout=subprocess.PIPE)
#         output, error = p1.communicate()
#         quota = " ".join(output.decode().split()).split(' ')
# #         self.logger.info("QUOTA: %s" %quota)
#         space = quota[1].strip('*') # I think the asterisk shows because the value is changing.
# #         self.logger.info("SPACE: %s" %space)
#         limit = quota[3]
        now = datetime.datetime.now()

        self.cpuUtil = self.thisProcess.cpu_percent()
        self.memUsage = self.thisProcess.memory_info()
        #         self.logger.info("rss: %s" %self.memUsage[0])
        # self.dbase.post(now=now , tag_dict={"disk":"space"}, seriesName="Disk", value=space)
        # self.dbase.post(now=now , tag_dict={"disk":"limit"}, seriesName="Disk", value=limit)
        self.dbase.post(now=now,
                        tag_dict={"cpu": "use"},
                        seriesName="CPU",
                        value=self.cpuUtil)
        self.dbase.post(now=now,
                        tag_dict={"mem": "rss"},
                        seriesName="Mem",
                        value=self.memUsage[0])
        self.dbase.post(now=now,
                        tag_dict={"mem": "vms"},
                        seriesName="Mem",
                        value=self.memUsage[1])

    def on_solve(self):

        timer = {}
        timer['start'] = time()
        now = self.solve.recv_pyobj()
        self.logger.info('PID(%s) - on_solve(): %s', str(self.pid), str(now))

        if self.connected:
            if (self.new_offers or self.solutions[self.time_interval] == {}):
                if self.new_offers:
                    self.logger.info("NEW OFFERS")
                if self.solutions[self.time_interval] == {}:
                    self.logger.info("NEW INTERVAL")
                self.ISID += 1
                self.solutions[self.time_interval][self.ISID] = None

                self.recordTime = True
                self.new_offers = False
                self.logger.info("Solving...")
                stopWatch = {
                    "interval": self.time_interval,
                    "start": time(),
                    "running": 1
                }

                #             self.logger.info("buying offers")
                #             for offer in self.buying_offers:
                #                 self.logger.info("%s, %s, %s, %s, %s" %(str(offer.ID), str(offer.prosumer), str(offer.startTime), str(offer.endTime), str(offer.energy)))
                #
                #             self.logger.info("selling offers")
                #             for offer in self.selling_offers:
                #                 self.logger.info("%s, %s, %s, %s, %s" %(str(offer.ID), str(offer.prosumer), str(offer.startTime), str(offer.endTime), str(offer.energy)))

                boffers = []
                for offer in self.buying_offers:
                    if offer.endTime < self.time_interval:
                        pass
                    elif offer.startTime <= self.time_interval + self.PREDICTION_WINDOW:
                        # print(offer.__dict__)
                        boffers.append(offer)

                soffers = []
                for offer in self.selling_offers:
                    if offer.endTime < self.time_interval:
                        pass
                    elif offer.startTime <= self.time_interval + self.PREDICTION_WINDOW:
                        # print(offer.__dict__)
                        soffers.append(offer)

                (solution,
                 objective) = self.solver.solve(boffers,
                                                soffers,
                                                finalized=self.finalized)
                stopWatch["split"] = time() - stopWatch["start"]
                now = datetime.datetime.now()

                self.logger.info(
                    "Solve Time: %s, buy offers: %s, sell offers: %s, total: %s"
                    % (stopWatch["split"], len(
                        self.buying_offers), len(self.selling_offers),
                       len(self.buying_offers) + len(self.selling_offers)))

                if objective > self.objective:
                    self.solution = solution
                    self.objective = objective
                    self.logger.info(
                        "interval: {}, New solution: (objective = {}).".format(
                            self.time_interval, objective))

                    self.interval_trades[self.time_interval] = 0
                    for offer in self.solution:
                        self.logger.info("interval: %s; trade interval: %s" %
                                         (self.time_interval, offer['t']))
                        if offer['t'] == self.time_interval:
                            self.interval_trades[
                                self.time_interval] += offer['p']
                    energy = self.interval_trades[self.time_interval]
                    self.logger.info(
                        "Interval: {}, Proposed Energy: {}".format(
                            self.time_interval, energy))

                    if not self.waiting_solutionID:
                        self.contract.createSolution(self.account,
                                                     self.solverID)
                        self.waiting_solutionID = True
                        self.logger.info(
                            "Trades will be submitted once a solution is created in the contract."
                        )
                else:
                    self.logger.info(
                        "No better solution found (objective = {}).".format(
                            objective))

            try:
                self.dbase.post(now=datetime.datetime.now(),
                                tag_dict={"resource": "storage"},
                                seriesName="Waste",
                                value=os.stat(self.logpath).st_size)
            except FileNotFoundError as e:
                self.logger.info("file does not exist")

    #         self.waste()
            timer['stop'] = time()
            timer['split'] = timer['stop'] - timer['start']
            if self.recordTime:

                self.recordTime = False
                self.logger.info("SOLVE TIME: %s PREDICTION WINDOW: %s" %
                                 (timer['split'], self.PREDICTION_WINDOW))
                error = timer['split'] - self.DeadLine
                self.dbase.post(
                    now=now,
                    tag_dict={"object": "Solver_" + str(self.solverID)},
                    seriesName="error",
                    value=error)

                self.priorPW = self.PREDICTION_WINDOW
                self.PREDICTION_WINDOW = self.PREDICTION_WINDOW + 5  #- self.Pgain*error
                if self.PREDICTION_WINDOW < 0:
                    self.PREDICTION_WINDOW = 0
                if self.PREDICTION_WINDOW > self.PWMax:
                    self.PREDICTION_WINDOW = self.PWMax

                self.dbase.post(
                    now=now,
                    tag_dict={"object": "Solver_" + str(self.solverID)},
                    seriesName="PW",
                    value=self.PREDICTION_WINDOW)
                self.dbase.post(
                    now=now,
                    tag_dict={"object": "Solver_" + str(self.solverID)},
                    seriesName="on_solve_time",
                    value=timer["split"])
                self.dbase.post(
                    now=now,
                    tag_dict={"object": "Solver_" + str(self.solverID)},
                    seriesName="solveTime",
                    value=stopWatch["split"])

    def handleSpcLimit(self):
        '''This is a function called by the riaps platform and should be generated if we are doing disk limits'''
        self.logger.warning('handleSpcLimit() ')
        try:
            with open(self.logpath,
                      'w'):  #opening the log file like this truncates it.
                pass
#             os.remove(self.logpath)
#             os.remove(self.name)
#             self.size = self.delta
#             now = datetime.datetime.now()
#             self.dbase.post(now=now, tag_dict={"resource":"storage"}, seriesName="Waste", value=self.size)

        except FileNotFoundError as e:
            self.logger.info("handleSpcLimit: Remove Error = %s" % e)
            self.logger.info("file does not exist")

    def handleMemLimit(self):
        now = datetime.datetime.now()
        memNow = self.thisProcess.memory_info()
        self.logger.warning('handleMEMLimit(): %s' % str(memNow))
        self.PWMax = self.priorPW - 1
        self.dbase.post(now=now,
                        tag_dict={"object": "Solver_" + str(self.solverID)},
                        seriesName="RSSNow",
                        value=memNow[0])
        self.dbase.post(now=now,
                        tag_dict={"object": "Solver_" + str(self.solverID)},
                        seriesName="PWMax",
                        value=self.PWMax)

    def handleDeadline(self, funcName):
        self.logger.warning("handleDeadline(): %s" % funcName)
        #if self.self.Pgain += 1
        self.PWMax = self.priorPW - 1
        self.dbase.post(now=datetime.datetime.now(),
                        tag_dict={"object": "Solver_" + str(self.solverID)},
                        seriesName="PWMax",
                        value=self.PWMax)

    def handleCPULimit(self):
        self.logger.warning('handleCPULimit()')
        self.PWMax = self.priorPW - 1
        self.dbase.post(now=datetime.datetime.now(),
                        tag_dict={"object": "Solver_" + str(self.solverID)},
                        seriesName="PWMax",
                        value=self.PWMax)

    def handleNICStateChange(self, state):
        if state == "down":
            self.logger.warning("NIC is %s" % state)
            # lost connection to contract
            self.connected = 0
            # self.connectGrafana()
            self.dbase.post(
                now=datetime.datetime.now(),
                tag_dict={"object": "Solver_" + str(self.solverID)},
                seriesName="PWMax",
                value=self.PWMax)
        else:
            self.logger.warning("NIC is %s" % state)

    def __destroy__(self):
        self.logger.info("(PID %s) - stopping Solver", 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 waste(self):
        self.logger.info("WASTE %s" % self.s)
Ejemplo n.º 8
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")
Ejemplo n.º 9
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")