def collect_values_from_nodes(self, nodes, node_list, measurement_types, ucallback=None, sampling_time=0, reporting_period=0, iterations=1):
        """ Defines the function that is called when a bunch of measurements are received from nodes.
            Than, executes the UPI_R.getMonitorBounce function on nodes, passed by argument.

        :param nodes: list of WiFiNode.
        :param node_list: list of Node.
        :param measurement_types: list of measurements name.
        :param ucallback: user-defined callback to be called after any reporting period
        :param sampling_time: the sampling time in [us] which the measurement is taken in the NIC
        :param reporting_period: period in [us] between two consecutive measurement reporting
        :param iterations: number of consecutive measurement reporting
        """

        res_measurements = []

        def monitorCallback(json_message):
            """  Is called when a bunch of measurements are received from nodes.
                 Extracts the ip address of the sender node and uses it to find appropriate object in WiFiNode list.
                 Stores the bunch of measurements in last_bunch_measurement WiFinode attribute.

            :param json_message: message received from node every iterations.
            """

            time_val = json_message['time']
            peer_node = json_message['peer']
            messagedata = json_message['msg']
            callback_id = json_message['callbackId']
            res_measurements.append(1)

            # add every response in a wifinode element
            for node in nodes:
                if node.getIpAddress() == callback_id.split('//')[1].split(':')[0] and messagedata != False:
                    node.last_bunch_measurement.append(messagedata)

            # call user-defined callback (the controller logic)
            ucallback(messagedata)

            return

        self.log.info('CALL getMonitor bunch  ....')
        now = get_now_full_second()
        UPIfunc = UPI_RN.getMonitorBounce
        UPIargs = {'measurements': measurement_types, 'slot_period': sampling_time, 'frame_period': reporting_period,
                   'interface': 'wlan0', 'iterator': iterations}
        print "UPIargs are ", UPIargs

        exec_time = now + timedelta(seconds=2)
        callback = monitorCallback
        try:
            self.mytestbed.global_mgr.runAt(node_list, UPIfunc, UPIargs, unix_time_as_tuple(exec_time), callback)
        except Exception as e:
            self.log.warning("An error occurred (e.g. scheduling events in the past): %s" % e)

        # plot data
        self.measurement_types = measurement_types

        return
 def stop_local_controller(mytestbed):
     CtrlFuncImpl = UPI_RN.stopFunc
     CtrlFuncargs =  {'INTERFACE' : ['wlan0']}
     now = get_now_full_second()
     # exec immediately
     exec_time = now + timedelta(seconds=3)
     log.info('Stop local WiSHFUL controller on all nodes - stop at : %s', str(exec_time))
     #nodes = upi_hc.getNodes()
     nodes = mytestbed.nodes
     try:
         callback = partial(resultCollector, funcId=99)
         mytestbed.global_mgr.runAt(nodes, UPI_RN.stopFunc, CtrlFuncargs, unix_time_as_tuple(exec_time), callback)
     except Exception as e:
         log.fatal("An error occurred when stop the local WiSHFUL controller: %s" % e)
    def collect_values_from_nodes(self,
                                  nodes,
                                  node_list,
                                  measurement_types,
                                  ucallback=None,
                                  sampling_time=0,
                                  reporting_period=0,
                                  iterations=1):
        """ Defines the function that is called when a bunch of measurements are received from nodes.
            Than, executes the UPI_R.getMonitorBounce function on nodes, passed by argument.

        :param nodes: list of WiFiNode.
        :param node_list: list of Node.
        :param measurement_types: list of measurements name.
        :param ucallback: user-defined callback to be called after any reporting period
        :param sampling_time: the sampling time in [us] which the measurement is taken in the NIC
        :param reporting_period: period in [us] between two consecutive measurement reporting
        :param iterations: number of consecutive measurement reporting
        """

        res_measurements = []

        def monitorCallback(json_message):
            """  Is called when a bunch of measurements are received from nodes.
                 Extracts the ip address of the sender node and uses it to find appropriate object in WiFiNode list.
                 Stores the bunch of measurements in last_bunch_measurement WiFinode attribute.

            :param json_message: message received from node every iterations.
            """

            time_val = json_message['time']
            peer_node = json_message['peer']
            messagedata = json_message['msg']
            callback_id = json_message['callbackId']
            res_measurements.append(1)

            # add every response in a wifinode element
            for node in nodes:
                if node.getIpAddress() == callback_id.split('//')[1].split(
                        ':')[0] and messagedata != False:
                    node.last_bunch_measurement.append(messagedata)

            # call user-defined callback (the controller logic)
            ucallback(messagedata)

            return

        self.log.info('CALL getMonitor bunch  ....')
        now = get_now_full_second()
        UPIfunc = UPI_RN.getMonitorBounce
        UPIargs = {
            'measurements': measurement_types,
            'slot_period': sampling_time,
            'frame_period': reporting_period,
            'interface': 'wlan0',
            'iterator': iterations
        }
        print "UPIargs are ", UPIargs

        exec_time = now + timedelta(seconds=2)
        callback = monitorCallback
        try:
            self.mytestbed.global_mgr.runAt(node_list, UPIfunc, UPIargs,
                                            unix_time_as_tuple(exec_time),
                                            callback)
        except Exception as e:
            self.log.warning(
                "An error occurred (e.g. scheduling events in the past): %s" %
                e)

        # plot data
        self.measurement_types = measurement_types

        return
def run_local_controller(mytestbed, disable=0):

    """
    Custom function used to implement local WiSHFUL controller
    """
    def customLocalCtrlFunction(myargs):

        import time
        import logging

        # references to Wishful framework
        global upiRNImpl # interface to UPI_R/N implementation
        global upiHCImpl # interface used for communication with global controller and control runtime

        log = logging.getLogger()
        log.warning('*********** WISHFUL SC3 *************')
        log.warning('*********** starting local WiSHFUL controller **********************')
        last_freezing_number = 0


        b = 0.1
        a = 0.1
        last_count_freezing = 0
        CWMIN = 15
        CWMAX = 1023
        T = 0.5 #0.1
        ipt = 0
        cw_f = CWMIN
        cycle_update = 0

        while not upiHCImpl.stopIsSet():

            UPIargs = {'iface' : 'wlan0' }
            ip_address = upiRNImpl.getIfaceIpAddr(UPIargs)
            cycle_update += 1

            #get freezing number
            #UPIfunc = UPI_RN.getMonitor
            UPIargs = {'KEY' : (UPI_RN.NUM_FREEZING_COUNT, 'wlan0' )}
            current_freezing_number = upiRNImpl.getMonitor(UPIargs)
            count_freezing = current_freezing_number[0]

            #Find/Compute CW good
            delta_freezing = count_freezing - last_count_freezing
            if delta_freezing < 0 :
                delta_freezing = 65535 - last_count_freezing + count_freezing
            last_count_freezing = count_freezing

            ipt = ipt + a * (delta_freezing - ipt)
            # #targetcw = -0.0131 * ipt ** 2 + 3.2180 * ipt + 13.9265;  # determine the target CW for this IPT
            targetcw = -1.3539 * ipt ** 2 + 7.6655 * ipt + 15.4545;  # determine the target CW for this IPT ver 25-11-2015 on TTILAB with 2,4,6 nodes samples.
            # calculate new smoothed CW
            cw_f = cw_f + b * (targetcw - cw_f);
            cw = round(cw_f);
            cw = int(cw)
            cw = max(cw,CWMIN);
            cw = min(cw,CWMAX);
            #cw = 50

            #update CW value
            UPIargs = {'KEY' : (UPI_RN.CSMA_CW, UPI_RN.CSMA_CW_MIN, UPI_RN.CSMA_CW_MAX, 'wlan0' ), 'VALUE' : [cw, cw, cw ]}
            upiRNImpl.setParameterLowerLayer(UPIargs)

            if not(cycle_update % 10):
                #communicate with global controller by passing control message
                upiHCImpl.transmitCtrlMsgUpstream( { "MEASURE" : [[count_freezing, cw]], "IP_ADDRESS" : (ip_address) } )
                log.info('current freezing number : %d' % (last_count_freezing))

            #wait next update time
            time.sleep(T)

        return 'Local WiSHFUL Controller END'

    """
    Custom callback function used to receive result values from scheduled calls, i.e. if you schedule the execution of a
    particular UPI_R/N function in the future this callback allows you to be informed about any function return values.
    """
    numCBs = {}
    numCBs['res'] = 0
    # use in while to lern if the local logic stopped e.g.
    # while numCBs['res'] < 2:

    def resultCollector(json_message, funcId):
        log.info('json: %s' % json_message)
        time_val = json_message['time']
        peer_node = json_message['peer']
        messagedata = json_message['msg']
        log.info('Callback %d: Local controller receives data msg at %s from %s : %s' % (funcId, str(time_val), peer_node, messagedata))
        numCBs['res'] = numCBs['res'] + 1

    """
    Custom callback function used to receive control feedback results from local controllers.
    """
    def ctrlMsgCollector(json_message):
        time_val = json_message['time']
        peer_node = json_message['peer']
        msg_data = json_message['msg']
        remote_wlan_ipAddress = msg_data['IP_ADDRESS']
        measurement_types = 'MEASURE'
        measurement = msg_data['MEASURE']
        log.info('Global controller receives ctrl msg at %s from %s : %s' % (str(time_val), peer_node, str(msg_data) ))

        # add measurement on nodes element
        for node in mytestbed.wifinodes:
            if node.wlan_ipAddress == remote_wlan_ipAddress and measurement != False:
                node.last_bunch_measurement.append(measurement)
                #log.debug('Append measurements at node %s : %s' % (str(remote_wlan_ipAddress), str(measurement) ))

    """
    Stop function used to send stop function to local controllers.
    """
    def stop_local_controller(mytestbed):
        CtrlFuncImpl = UPI_RN.stopFunc
        CtrlFuncargs =  {'INTERFACE' : ['wlan0']}
        now = get_now_full_second()
        # exec immediately
        exec_time = now + timedelta(seconds=3)
        log.info('Stop local WiSHFUL controller on all nodes - stop at : %s', str(exec_time))
        #nodes = upi_hc.getNodes()
        nodes = mytestbed.nodes
        try:
            callback = partial(resultCollector, funcId=99)
            mytestbed.global_mgr.runAt(nodes, UPI_RN.stopFunc, CtrlFuncargs, unix_time_as_tuple(exec_time), callback)
        except Exception as e:
            log.fatal("An error occurred when stop the local WiSHFUL controller: %s" % e)


    # START MAIN PART

    if disable:
        stop_local_controller(mytestbed)
        return

    # register callback function for collecting results
    mytestbed.global_mgr.setCtrlCollector(ctrlMsgCollector)
    # deploy a custom control program on each node
    CtrlFuncImpl = customLocalCtrlFunction
    CtrlFuncargs =  {'INTERFACE' : ['wlan0']}
    # get current time
    now = get_now_full_second()
    # exec immediately
    exec_time = now + timedelta(seconds=3)
    log.info('Sending local WiSHFUL controller on all nodes - start at : %s', str(exec_time))

    #nodes = upi_hc.getNodes()
    for node in mytestbed.wifinodes:
        node.measurement_types.append('FREEZING_NUMBER')
        node.measurement_types.append('CW')
    nodes = mytestbed.nodes

    try:
        # this is a non-blocking call
        callback = partial(resultCollector, funcId=99)
        #isOntheflyReconfig = True
        mytestbed.global_mgr.runAt(nodes, CtrlFuncImpl, CtrlFuncargs, unix_time_as_tuple(exec_time), callback )
    except Exception as e:
        log.fatal("An error occurred in local controller WiSHFUL sending and running : %s" % e)

    log.info("Local logic STARTED")
    return