Пример #1
0
    def __init__(self, dev, revision=DEFAULT_REVISION):
        '''
        Instantiates the KillerBee class for the ApiMote platform running GoodFET firmware.
        @type dev:   String
        @param dev:  Serial device identifier (ex /dev/ttyUSB0)
        @type revision: Integer
        @param revision: The revision number for the ApiMote, which is used by 
            the called GoodFET libraries to properly communicate with
            and configure the hardware.
        @return: None
        @rtype: None
        '''
        self._channel = None
        self._page = 0
        self.handle = None
        self.dev = dev

        self.__revision_num = revision
        # Set enviroment variables for GoodFET code to use
        os.environ["platform"] = "apimote%d".format(self.__revision_num)
        os.environ["board"] = "apimote%d".format(self.__revision_num)
        self.handle = GoodFETCCSPI()
        self.handle.serInit(port=self.dev)
        self.handle.setup()
        # TODO can we verify here the revision number that was sent is correct?

        self.__stream_open = False
        self.capabilities = KBCapabilities()
        self.__set_capabilities()
Пример #2
0
def isgoodfetccspi(serialdev):
    '''
    Determine if a given serial device is a TelosB/Tmote Sky GOODFET (with CCSPI application).
    @type serialdev: String
    @param serialdev: Path to a serial device, ex /dev/ttyUSB0.
    @rtype: Boolean
    '''
    from GoodFETCCSPI import GoodFETCCSPI
    os.environ["platform"] = "telosb" #set enviroment variable for GoodFET code to use
    gf = GoodFETCCSPI()
    gf.serInit(port=serialdev, attemptlimit=2)
    status = (gf.connected == 1)
    gf.serClose()
    return status
Пример #3
0
    def __init__(self, dev, revision=DEFAULT_REVISION):
        '''
        Instantiates the KillerBee class for the ApiMote platform running GoodFET firmware.
        @type dev:   String
        @param dev:  Serial device identifier (ex /dev/ttyUSB0)
        @type revision: Integer
        @param revision: The revision number for the ApiMote, which is used by 
            the called GoodFET libraries to properly communicate with
            and configure the hardware.
        @return: None
        @rtype: None
        '''
        self._channel = None
        self.handle = None
        self.dev = dev

        self.__revision_num = revision
        # Set enviroment variables for GoodFET code to use
        os.environ["platform"] = "apimote%d".format(self.__revision_num)
        os.environ["board"] = "apimote%d".format(self.__revision_num)
        self.handle = GoodFETCCSPI()
        self.handle.serInit(port=self.dev)
        self.handle.setup()
        # TODO can we verify here the revision number that was sent is correct?

        self.__stream_open = False
        self.capabilities = KBCapabilities()
        self.__set_capabilities()
Пример #4
0
    def __init__(self, dev):
        '''
        Instantiates the KillerBee class for our TelosB/TmoteSky running GoodFET firmware.
        @type dev:   String
        @param dev:  Serial device identifier (ex /dev/ttyUSB0)
        @return: None
        @rtype: None
        '''
        self._channel = None
        self.handle = None
        self.dev = dev

        os.environ["board"] = "telosb" #set enviroment variable for GoodFET code to use
        self.handle = GoodFETCCSPI()
        self.handle.serInit(port=self.dev)
        self.handle.setup()

        self.__stream_open = False
        self.capabilities = KBCapabilities()
        self.__set_capabilities()
Пример #5
0
def isgoodfetccspi(serialdev):
    '''
    Determine if a given serial device is running the GoodFET firmware with the CCSPI application.
    This should either be a TelosB/Tmote Sky GOODFET or an Api-Mote design.
    @type serialdev:  String
    @param serialdev: Path to a serial device, ex /dev/ttyUSB0.
    @rtype:   Tuple
    @returns: Tuple with the fist element==True if it is some goodfetccspi device. The second element
                is the subtype, and is 0 for telosb devices and 1 for apimote devices.
    '''
    #TODO reduce code, perhaps into loop iterating over board configs
    from GoodFETCCSPI import GoodFETCCSPI
    os.environ["platform"] = ""
    # First try tmote detection
    os.environ[
        "board"] = "telosb"  #set enviroment variable for GoodFET code to use
    gf = GoodFETCCSPI()
    try:
        gf.serInit(port=serialdev, attemptlimit=2)
    except serial.serialutil.SerialException as e:
        raise KBInterfaceError("Serial issue in kbutils.isgoodfetccspi: %s." %
                               e)
    if gf.connected == 1:
        #print "TelosB/Tmote attempts: found %s on %s" % (gf.identstr(), serialdev)
        # now check if ccspi app is installed
        out = gf.writecmd(gf.CCSPIAPP, 0, 0, None)
        gf.serClose()
        if (gf.app == gf.CCSPIAPP) and (gf.verb == 0):
            return True, 0
    # Try apimote v2 detection
    os.environ[
        "board"] = "apimote2"  #set enviroment variable for GoodFET code to use
    gf = GoodFETCCSPI()
    try:
        gf.serInit(port=serialdev, attemptlimit=2)
        #gf.setup()
    except serial.serialutil.SerialException as e:
        raise KBInterfaceError("Serial issue in kbutils.isgoodfetccspi: %s." %
                               e)
    if gf.connected == 1:
        #print "ApiMotev2+ attempts: found %s on %s" % (gf.identstr(), serialdev)
        # now check if ccspi app is installed
        out = gf.writecmd(gf.CCSPIAPP, 0, 0, None)
        gf.serClose()
        if (gf.app == gf.CCSPIAPP) and (gf.verb == 0):
            return True, 2
    # Then try apimote v1 detection
    os.environ[
        "board"] = "apimote1"  #set enviroment variable for GoodFET code to use
    gf = GoodFETCCSPI()
    try:
        #TODO note that in ApiMote v1, this connect appears to be tricky sometimes
        #     thus attempt limit is raised to 4 for now
        #     manually verify the hardware is working by using direct GoodFET client commands, such as:
        #       export board=apimote1; ./goodfet.ccspi info; ./goodfet.ccspi spectrum
        gf.serInit(port=serialdev, attemptlimit=4)
        #gf.setup()
        #print "Found %s on %s" % (gf.identstr(), serialdev)
    except serial.serialutil.SerialException as e:
        raise KBInterfaceError("Serial issue in kbutils.isgoodfetccspi: %s." %
                               e)
    if gf.connected == 1:
        #print "ApiMotev1 attempts: found %s on %s" % (gf.identstr(), serialdev)
        # now check if ccspi app is installed
        out = gf.writecmd(gf.CCSPIAPP, 0, 0, None)
        gf.serClose()
        if (gf.app == gf.CCSPIAPP) and (gf.verb == 0):
            return True, 1
    # Nothing found
    return False, None
Пример #6
0
def isgoodfetccspi(serialdev):
    '''
    Determine if a given serial device is running the GoodFET firmware with the CCSPI application.
    This should either be a TelosB/Tmote Sky GOODFET or an Api-Mote design.
    @type serialdev:  String
    @param serialdev: Path to a serial device, ex /dev/ttyUSB0.
    @rtype:   Tuple
    @returns: Tuple with the fist element==True if it is some goodfetccspi device. The second element
                is the subtype, and is 0 for telosb devices and 1 for apimote devices.
    '''
    #TODO reduce code, perhaps into loop iterating over board configs
    from GoodFETCCSPI import GoodFETCCSPI
    os.environ["platform"] = ""
    # First try tmote detection
    os.environ["board"] = "telosb" #set enviroment variable for GoodFET code to use
    gf = GoodFETCCSPI()
    try:
        gf.serInit(port=serialdev, attemptlimit=2)
    except serial.serialutil.SerialException as e:
        raise KBInterfaceError("Serial issue in kbutils.isgoodfetccspi: %s." % e)
    if gf.connected == 1:
        #print "TelosB/Tmote attempts: found %s on %s" % (gf.identstr(), serialdev)
        # now check if ccspi app is installed
        out = gf.writecmd(gf.CCSPIAPP, 0, 0, None)
        gf.serClose()        
        if (gf.app == gf.CCSPIAPP) and (gf.verb == 0):
            return True, 0
    # Try apimote v2 detection
    os.environ["board"] = "apimote2" #set enviroment variable for GoodFET code to use
    gf = GoodFETCCSPI()
    try:
        gf.serInit(port=serialdev, attemptlimit=2)
        #gf.setup()
    except serial.serialutil.SerialException as e:
        raise KBInterfaceError("Serial issue in kbutils.isgoodfetccspi: %s." % e)    
    if gf.connected == 1:
        #print "ApiMotev2+ attempts: found %s on %s" % (gf.identstr(), serialdev)
        # now check if ccspi app is installed
        out = gf.writecmd(gf.CCSPIAPP, 0, 0, None)
        gf.serClose()        
        if (gf.app == gf.CCSPIAPP) and (gf.verb == 0):
            return True, 2
    # Then try apimote v1 detection
    os.environ["board"] = "apimote1" #set enviroment variable for GoodFET code to use
    gf = GoodFETCCSPI()
    try:
        #TODO note that in ApiMote v1, this connect appears to be tricky sometimes
        #     thus attempt limit is raised to 4 for now
        #     manually verify the hardware is working by using direct GoodFET client commands, such as:
        #       export board=apimote1; ./goodfet.ccspi info; ./goodfet.ccspi spectrum
        gf.serInit(port=serialdev, attemptlimit=4)
        #gf.setup()
        #print "Found %s on %s" % (gf.identstr(), serialdev)
    except serial.serialutil.SerialException as e:
        raise KBInterfaceError("Serial issue in kbutils.isgoodfetccspi: %s." % e)    
    if gf.connected == 1:
        #print "ApiMotev1 attempts: found %s on %s" % (gf.identstr(), serialdev)
        # now check if ccspi app is installed
        out = gf.writecmd(gf.CCSPIAPP, 0, 0, None)
        gf.serClose()        
        if (gf.app == gf.CCSPIAPP) and (gf.verb == 0):
            return True, 1
    # Nothing found
    return False, None
Пример #7
0
class APIMOTE:
    def __init__(self, dev, revision=DEFAULT_REVISION):
        '''
        Instantiates the KillerBee class for the ApiMote platform running GoodFET firmware.
        @type dev:   String
        @param dev:  Serial device identifier (ex /dev/ttyUSB0)
        @type revision: Integer
        @param revision: The revision number for the ApiMote, which is used by 
            the called GoodFET libraries to properly communicate with
            and configure the hardware.
        @return: None
        @rtype: None
        '''
        self._channel = None
        self.handle = None
        self.dev = dev

        self.__revision_num = revision
        # Set enviroment variables for GoodFET code to use
        os.environ["platform"] = "apimote%d".format(self.__revision_num)
        os.environ["board"] = "apimote%d".format(self.__revision_num)
        self.handle = GoodFETCCSPI()
        self.handle.serInit(port=self.dev)
        self.handle.setup()
        # TODO can we verify here the revision number that was sent is correct?

        self.__stream_open = False
        self.capabilities = KBCapabilities()
        self.__set_capabilities()

    def close(self):
        self.handle.serClose()
        self.handle = None

    def check_capability(self, capab):
        return self.capabilities.check(capab)
    def get_capabilities(self):
        return self.capabilities.getlist()
    def __set_capabilities(self):
        '''
        Sets the capability information appropriate for GoodFETCCSPI client and firmware.
        @rtype: None
        @return: None
        '''
        self.capabilities.setcapab(KBCapabilities.FREQ_2400, True)
        self.capabilities.setcapab(KBCapabilities.SNIFF, True)
        self.capabilities.setcapab(KBCapabilities.SETCHAN, True)
        self.capabilities.setcapab(KBCapabilities.INJECT, True)
        self.capabilities.setcapab(KBCapabilities.PHYJAM_REFLEX, True)
        self.capabilities.setcapab(KBCapabilities.SET_SYNC, True)
        return

    # KillerBee expects the driver to implement this function
    def get_dev_info(self):
	'''
        Returns device information in a list identifying the device.
        @rtype: List
        @return: List of 3 strings identifying device.
        '''
        return [self.dev, "GoodFET Apimote v%d".format(self.__revision_num), ""]

    # KillerBee expects the driver to implement this function
    def sniffer_on(self, channel=None):
        '''
        Turns the sniffer on such that pnext() will start returning observed
        data.  Will set the command mode to Air Capture if it is not already
        set.
        @type channel: Integer
        @param channel: Sets the channel, optional
        @rtype: None
        '''
        self.capabilities.require(KBCapabilities.SNIFF)

        self.handle.RF_promiscuity(1);
        self.handle.RF_autocrc(0);

        if channel != None:
            self.set_channel(channel)
        
        self.handle.CC_RFST_RX();
        #print "Sniffer started (listening as %010x on %i MHz)" % (self.handle.RF_getsmac(), self.handle.RF_getfreq()/10**6);

        self.__stream_open = True

    # KillerBee expects the driver to implement this function
    def sniffer_off(self):
        '''
        Turns the sniffer off, freeing the hardware for other functions.  It is
        not necessary to call this function before closing the interface with
        close().
        @rtype: None
        '''
        #TODO actually have firmware stop sending us packets!
        self.__stream_open = False

    # KillerBee expects the driver to implement this function
    def set_channel(self, channel):
        '''
        Sets the radio interface to the specifid channel (limited to 2.4 GHz channels 11-26)
        @type channel: Integer
        @param channel: Sets the channel, optional
        @rtype: None
        '''
        self.capabilities.require(KBCapabilities.SETCHAN)

        if channel >= 11 or channel <= 26:
            self._channel = channel
            self.handle.RF_setchan(channel)
        else:
            raise Exception('Invalid channel')

    # KillerBee expects the driver to implement this function
    def inject(self, packet, channel=None, count=1, delay=0):
        '''
        Injects the specified packet contents.
        @type packet: String
        @param packet: Packet contents to transmit, without FCS.
        @type channel: Integer
        @param channel: Sets the channel, optional
        @type count: Integer
        @param count: Transmits a specified number of frames, def=1
        @type delay: Float
        @param delay: Delay between each frame, def=1
        @rtype: None
        '''
        self.capabilities.require(KBCapabilities.INJECT)

        if len(packet) < 1:
            raise Exception('Empty packet')
        if len(packet) > 125:                   # 127 - 2 to accommodate FCS
            raise Exception('Packet too long')

        if channel != None:
            self.set_channel(channel)

        self.handle.RF_autocrc(1)               #let radio add the CRC
        for pnum in range(0, count):
            gfready = [ord(x) for x in packet]  #convert packet string to GoodFET expected integer format
            gfready.insert(0, len(gfready)+2)   #add a length that leaves room for CRC
            self.handle.RF_txpacket(gfready)
            time.sleep(1)

    # KillerBee expects the driver to implement this function
    def pnext(self, timeout=100):
        '''
        Returns a dictionary containing packet data, else None.
        @type timeout: Integer
        @param timeout: Timeout to wait for packet reception in usec
        @rtype: List
        @return: Returns None is timeout expires and no packet received.  When a packet is received, a dictionary is returned with the keys bytes (string of packet bytes), validcrc (boolean if a vaid CRC), rssi (unscaled RSSI), and location (may be set to None). For backwards compatibility, keys for 0,1,2 are provided such that it can be treated as if a list is returned, in the form [ String: packet contents | Bool: Valid CRC | Int: Unscaled RSSI ]
        '''
        if self.__stream_open == False:
            self.sniffer_on() #start sniffing

        packet = None;
        start = datetime.utcnow()

        while (packet is None and (start + timedelta(microseconds=timeout) > datetime.utcnow())):
            packet = self.handle.RF_rxpacket()
            rssi = self.handle.RF_getrssi() #TODO calibrate

        if packet is None:
            return None

        frame = packet[1:]
        if frame[-2:] == makeFCS(frame[:-2]): validcrc = True
        else: validcrc = False
        #Return in a nicer dictionary format, so we don't have to reference by number indicies.
        #Note that 0,1,2 indicies inserted twice for backwards compatibility.
        result = {0:frame, 1:validcrc, 2:rssi, 'bytes':frame, 'validcrc':validcrc, 'rssi':rssi, 'location':None}
        result['dbm'] = rssi - 45 #TODO tune specifically to the Apimote platform (does ext antenna need to different?)
        result['datetime'] = datetime.utcnow()
        return result
 
    def ping(self, da, panid, sa, channel=None):
        '''
        Not yet implemented.
        @return: None
        @rtype: None
        '''
        raise Exception('Not yet implemented')

    def jammer_on(self, channel=None):
        '''
        Not yet implemented.
        @type channel: Integer
        @param channel: Sets the channel, optional
        @rtype: None
        '''
        self.capabilities.require(KBCapabilities.PHYJAM_REFLEX)

        self.handle.RF_promiscuity(1)
        self.handle.RF_autocrc(0)
        if channel != None:
            self.set_channel(channel)
        self.handle.CC_RFST_RX()
        self.handle.RF_carrier() #constant carrier wave jamming
        #self.handle.RF_reflexjam() #reflexive jamming (advanced)

    def set_sync(self, sync=0xA70F):
        '''Set the register controlling the 802.15.4 PHY sync byte.'''
        self.capabilities.require(KBCapabilities.SET_SYNC)
        if (sync >> 16) > 0:
            raise Exception("Sync word (%x) must be 2-bytes or less." % sync)
        return self.handle.poke(CC2420_REG_SYNC, sync)

    def jammer_off(self, channel=None):
        '''
        Not yet implemented.
        @return: None
        @rtype: None
        '''
        #TODO implement
        raise Exception('Not yet implemented')
Пример #8
0
from sugar.activity import activity
import logging

import sys, os
import gtk

from GoodFETCCSPI import GoodFETCCSPI;

client = GoodFETCCSPI();

class GoodFETActivity(activity.Activity):
     def butConnectClicked(self, widget, data=None):
         logging.info('Attempting to connect.');
         client.serInit();
         client.setup();
         logging.info("Connected.");
         self.butConnect.set_label("Connected to %s" % client.identstr());
 
     def __init__(self, handle):
         print "running activity init", handle
         activity.Activity.__init__(self, handle)
         print "activity running"
 
         # Creates the Toolbox. It contains the Activity Toolbar, which is the
         # bar that appears on every Sugar window and contains essential
         # functionalities, such as the 'Collaborate' and 'Close' buttons.
         toolbox = activity.ActivityToolbox(self)
         self.set_toolbox(toolbox)
         toolbox.show()
 
         # Creates a new button with the label "Hello World".
Пример #9
0
class APIMOTE:
    def __init__(self, dev, revision=DEFAULT_REVISION):
        '''
        Instantiates the KillerBee class for the ApiMote platform running GoodFET firmware.
        @type dev:   String
        @param dev:  Serial device identifier (ex /dev/ttyUSB0)
        @type revision: Integer
        @param revision: The revision number for the ApiMote, which is used by 
            the called GoodFET libraries to properly communicate with
            and configure the hardware.
        @return: None
        @rtype: None
        '''
        self._channel = None
        self._page = 0
        self.handle = None
        self.dev = dev

        self.__revision_num = revision
        # Set enviroment variables for GoodFET code to use
        os.environ["platform"] = "apimote%d".format(self.__revision_num)
        os.environ["board"] = "apimote%d".format(self.__revision_num)
        self.handle = GoodFETCCSPI()
        self.handle.serInit(port=self.dev)
        self.handle.setup()
        # TODO can we verify here the revision number that was sent is correct?

        self.__stream_open = False
        self.capabilities = KBCapabilities()
        self.__set_capabilities()

    def close(self):
        self.handle.serClose()
        self.handle = None

    def check_capability(self, capab):
        return self.capabilities.check(capab)
    def get_capabilities(self):
        return self.capabilities.getlist()
    def __set_capabilities(self):
        '''
        Sets the capability information appropriate for GoodFETCCSPI client and firmware.
        @rtype: None
        @return: None
        '''
        self.capabilities.setcapab(KBCapabilities.FREQ_2400, True)
        self.capabilities.setcapab(KBCapabilities.SNIFF, True)
        self.capabilities.setcapab(KBCapabilities.SETCHAN, True)
        self.capabilities.setcapab(KBCapabilities.INJECT, True)
        self.capabilities.setcapab(KBCapabilities.PHYJAM_REFLEX, True)
        self.capabilities.setcapab(KBCapabilities.SET_SYNC, True)
        return

    # KillerBee expects the driver to implement this function
    def get_dev_info(self):
        '''
        Returns device information in a list identifying the device.
        @rtype: List
        @return: List of 3 strings identifying device.
        '''
        return [self.dev, "GoodFET Apimote v%d".format(self.__revision_num), ""]

    # KillerBee expects the driver to implement this function
    def sniffer_on(self, channel=None, page=0):
        '''
        Turns the sniffer on such that pnext() will start returning observed
        data.  Will set the command mode to Air Capture if it is not already
        set.
        @type channel: Integer
        @param channel: Sets the channel, optional
        @type page: Integer
        @param page: Sets the subghz page, not supported on this device
        @rtype: None
        '''
        self.capabilities.require(KBCapabilities.SNIFF)

        self.handle.RF_promiscuity(1)
        self.handle.RF_autocrc(0)

        if channel != None:
            self.set_channel(channel, page)
        
        self.handle.CC_RFST_RX()
        #print "Sniffer started (listening as %010x on %i MHz)" % (self.handle.RF_getsmac(), self.handle.RF_getfreq()/10**6);

        self.__stream_open = True

    # KillerBee expects the driver to implement this function
    def sniffer_off(self):
        '''
        Turns the sniffer off, freeing the hardware for other functions.  It is
        not necessary to call this function before closing the interface with
        close().
        @rtype: None
        '''
        #TODO actually have firmware stop sending us packets!
        self.__stream_open = False

    # KillerBee expects the driver to implement this function
    def set_channel(self, channel, page=0):
        '''
        Sets the radio interface to the specifid channel (limited to 2.4 GHz channels 11-26)
        @type channel: Integer
        @param channel: Sets the channel, optional
        @rtype: None
        '''
        self.capabilities.require(KBCapabilities.SETCHAN)

        if channel >= 11 or channel <= 26:
            self._channel = channel
            self.handle.RF_setchan(channel)
        else:
            raise Exception('Invalid channel')
        if page:
            raise Exception('SubGHz not supported')

    # KillerBee expects the driver to implement this function
    def inject(self, packet, channel=None, count=1, delay=0, page=0):
        '''
        Injects the specified packet contents.
        @type packet: String
        @param packet: Packet contents to transmit, without FCS.
        @type channel: Integer
        @param channel: Sets the channel, optional
        @type page: Integer
        @param page: Sets the subghz page, not supported on this device
        @type count: Integer
        @param count: Transmits a specified number of frames, def=1
        @type delay: Float
        @param delay: Delay between each frame, def=1
        @rtype: None
        '''
        self.capabilities.require(KBCapabilities.INJECT)

        if len(packet) < 1:
            raise Exception('Empty packet')
        if len(packet) > 125:                   # 127 - 2 to accommodate FCS
            raise Exception('Packet too long')

        if channel != None:
            self.set_channel(channel, page)

        self.handle.RF_autocrc(1)               #let radio add the CRC
        for pnum in range(0, count):
            gfready = [ord(x) for x in packet]  #convert packet string to GoodFET expected integer format
            gfready.insert(0, len(gfready)+2)   #add a length that leaves room for CRC
            self.handle.RF_txpacket(gfready)
            time.sleep(1)

    # KillerBee expects the driver to implement this function
    def pnext(self, timeout=100):
        '''
        Returns a dictionary containing packet data, else None.
        @type timeout: Integer
        @param timeout: Timeout to wait for packet reception in usec
        @rtype: List
        @return: Returns None is timeout expires and no packet received.  When a packet is received, a dictionary is returned with the keys bytes (string of packet bytes), validcrc (boolean if a vaid CRC), rssi (unscaled RSSI), and location (may be set to None). For backwards compatibility, keys for 0,1,2 are provided such that it can be treated as if a list is returned, in the form [ String: packet contents | Bool: Valid CRC | Int: Unscaled RSSI ]
        '''
        if self.__stream_open == False:
            self.sniffer_on()

        packet = None
        start = datetime.utcnow()

        while (packet is None and (start + timedelta(microseconds=timeout) > datetime.utcnow())):
            packet = self.handle.RF_rxpacket()
            rssi = self.handle.RF_getrssi() #TODO calibrate

        if packet is None:
            return None

        frame = packet[1:]
        validcrc = False
        if frame[-2:] == makeFCS(frame[:-2]):
            validcrc = True
        #Return in a nicer dictionary format, so we don't have to reference by number indicies.
        #Note that 0,1,2 indicies inserted twice for backwards compatibility.
        result = {0:frame, 1:validcrc, 2:rssi, 'bytes':frame, 'validcrc':validcrc, 'rssi':rssi, 'location':None}
        result['dbm'] = rssi - 45 #TODO tune specifically to the Apimote platform (does ext antenna need to different?)
        result['datetime'] = datetime.utcnow()
        return result
 
    def ping(self, da, panid, sa, channel=None, page=0):
        '''
        Not yet implemented.
        @return: None
        @rtype: None
        '''
        raise Exception('Not yet implemented')

    def jammer_on(self, channel=None, page=0):
        '''
        Not yet implemented.
        @type channel: Integer
        @param channel: Sets the channel, optional
        @type page: Integer
        @param page: Sets the subghz page, not supported on this device
        @rtype: None
        '''
        self.capabilities.require(KBCapabilities.PHYJAM_REFLEX)

        self.handle.RF_promiscuity(1)
        self.handle.RF_autocrc(0)
        if channel != None:
            self.set_channel(channel, page)
        self.handle.CC_RFST_RX()
        self.handle.RF_carrier() #constant carrier wave jamming
        #self.handle.RF_reflexjam() #reflexive jamming (advanced)

    def set_sync(self, sync=0xA70F):
        '''Set the register controlling the 802.15.4 PHY sync byte.'''
        self.capabilities.require(KBCapabilities.SET_SYNC)
        if (sync >> 16) > 0:
            raise Exception("Sync word (%x) must be 2-bytes or less." % sync)
        return self.handle.poke(CC2420_REG_SYNC, sync)

    def jammer_off(self, channel=None, page=0):
        '''
        Not yet implemented.
        @return: None
        @rtype: None
        '''
        #TODO implement
        raise Exception('Not yet implemented')