Esempio n. 1
0
class AntEasyTests(unittest.TestCase):
    @unittest.skipUnless("ANT_TEST_USB_STICK" in os.environ,
                         "Testing with USB stick not enabled")
    def test_search(self):

        try:
            logger = logging.getLogger("ant")
            logger.setLevel(logging.DEBUG)
            handler = logging.StreamHandler()
            handler.setFormatter(
                logging.Formatter(
                    fmt="%(asctime)s  %(name)-15s  %(levelname)-8s  %(message)s"
                ))
            logger.addHandler(handler)

            self.node = Node()
            print("Request basic information...")
            m = self.node.request_message(Message.ID.RESPONSE_ANT_VERSION)
            print("  ANT version:  ", struct.unpack("<10sx", m[2])[0])
            m = self.node.request_message(Message.ID.RESPONSE_CAPABILITIES)
            print("  Capabilities: ", m[2])
            m = self.node.request_message(Message.ID.RESPONSE_SERIAL_NUMBER)
            print("  Serial number:", struct.unpack("<I", m[2])[0])

            print("Starting system...")

            NETWORK_KEY = [0xA8, 0xA4, 0x23, 0xB9, 0xF5, 0x5E, 0x63, 0xC1]

            # self.node.reset_system()
            self.node.set_network_key(0x00, NETWORK_KEY)

            c = self.node.new_channel(Channel.Type.BIDIRECTIONAL_RECEIVE)

            c.set_period(4096)
            c.set_search_timeout(255)
            c.set_rf_freq(50)
            c.set_search_waveform([0x53, 0x00])
            c.set_id(0, 0x01, 0)

            print("Open channel...")
            c.open()
            c.request_message(Message.ID.RESPONSE_CHANNEL_STATUS)

            print("Searching...")

            self.node.start()

            print("Done")
        except KeyboardInterrupt:
            print("Interrupted")
            self.node.stop()
            sys.exit(1)

    def stop(self):
        self.node.stop()
Esempio n. 2
0
class AntEasyTests(unittest.TestCase):
    @unittest.skipUnless("ANT_TEST_USB_STICK" in os.environ, "Testing with USB stick not enabled")
    def test_search(self):

        try:
            logger = logging.getLogger("ant")
            logger.setLevel(logging.DEBUG)
            handler = logging.StreamHandler()
            handler.setFormatter(logging.Formatter(fmt='%(asctime)s  %(name)-15s  %(levelname)-8s  %(message)s'))
            logger.addHandler(handler)

            self.node = Node()
            print("Request basic information...")
            m = self.node.request_message(Message.ID.RESPONSE_ANT_VERSION)
            print("  ANT version:  ", struct.unpack("<10sx", m[2])[0])
            m = self.node.request_message(Message.ID.RESPONSE_CAPABILITIES)
            print("  Capabilities: ", m[2])
            m = self.node.request_message(Message.ID.RESPONSE_SERIAL_NUMBER)
            print("  Serial number:", struct.unpack("<I", m[2])[0])

            print("Starting system...")

            NETWORK_KEY = [0xa8, 0xa4, 0x23, 0xb9, 0xf5, 0x5e, 0x63, 0xc1]

            # self.node.reset_system()
            self.node.set_network_key(0x00, NETWORK_KEY)

            c = self.node.new_channel(Channel.Type.BIDIRECTIONAL_RECEIVE)

            c.set_period(4096)
            c.set_search_timeout(255)
            c.set_rf_freq(50)
            c.set_search_waveform([0x53, 0x00])
            c.set_id(0, 0x01, 0)

            print("Open channel...")
            c.open()
            c.request_message(Message.ID.RESPONSE_CHANNEL_STATUS)

            print("Searching...")

            self.node.start()

            print("Done")
        except KeyboardInterrupt:
            print("Interrupted")
            self.node.stop()
            sys.exit(1)

    def stop(self):
        self.node.stop()
class Application:
    
    _serial_number = 1337
    _frequency     = 19    # 0 to 124, x - 2400 (in MHz)
    
    def __init__(self):

        self._queue = Queue.Queue()
        self._beacons = Queue.Queue()

        self._node = Node()

        try:
            NETWORK_KEY= [0xa8, 0xa4, 0x23, 0xb9, 0xf5, 0x5e, 0x63, 0xc1]
            self._node.set_network_key(0x00, NETWORK_KEY)


            print "Request basic information..."

            m = self._node.request_message(Message.ID.RESPONSE_CAPABILITIES)
            print "  Capabilities: ", m[2]

            #m = self._node.request_message(Message.ID.RESPONSE_VERSION)
            #print "  ANT version:  ", struct.unpack("<10sx", m[2])[0]

            #m = self._node.request_message(Message.ID.RESPONSE_SERIAL_NUMBER)
            #print "  Serial number:", struct.unpack("<I", m[2])[0]

            print "Starting system..."

            #NETWORK_KEY= [0xa8, 0xa4, 0x23, 0xb9, 0xf5, 0x5e, 0x63, 0xc1]
            #self._node.set_network_key(0x00, NETWORK_KEY)

            print "Key done..."

            self._channel = self._node.new_channel(Channel.Type.BIDIRECTIONAL_RECEIVE)
            self._channel.on_broadcast_data = self._on_data
            self._channel.on_burst_data = self._on_data
            
            self.setup_channel(self._channel)
            
            self._worker_thread =threading.Thread(target=self._worker, name="ant.fs")
            self._worker_thread.start()
        except Exception as e:
            self.stop()
            raise e

    def _worker(self):
        self._node.start()

    def _main(self):
        try:
            _logger.debug("Link level")
            beacon = self._get_beacon()
            if self.on_link(beacon):
                for i in range(0, 5):
                    beacon = self._get_beacon()
                    if beacon.get_client_device_state() == Beacon.ClientDeviceState.AUTHENTICATION:
                        _logger.debug("Auth layer")
                        if self.on_authentication(beacon):
                            _logger.debug("Authenticated")
                            beacon = self._get_beacon()
                            self.on_transport(beacon)
                        self.disconnect()
                        break
        #except Exception as e:
        #    print e
        #    traceback.print_exc()
        #    for line in traceback.format_exc().splitlines():
        #        _logger.error("%r", line)
        finally:
            _logger.debug("Run 5")
            self.stop()


    def _on_beacon(self, data):
        b = Beacon.parse(data)
        self._beacons.put(b)

    def _on_command(self, data):
        c = ant.fs.command.parse(data)
        self._queue.put(c)

    def _on_data(self, data):
        #print "_on_data", data, len(data)
        if data[0] == 0x43:
            self._on_beacon(data[:8])
            if len(data[8:]) > 0:
                self._on_command(data[8:])
        elif data[0] == 0x44:
            self._on_command(data)
    
    def _get_beacon(self):
        b = self._beacons.get()
        self._beacons.task_done()
        return b
    
    def _get_command(self, timeout=3.0):
        _logger.debug("Get command, t%d, s%d", timeout, self._queue.qsize())
        c = self._queue.get(True, timeout)
        self._queue.task_done()
        return c
    
    def _send_command(self, c):
        data = c.get()
        if len(data) == 8:
            self._channel.send_acknowledged_data(data)
        else:
            self._channel.send_burst_transfer(data)
    
    # Application actions are defined from here
    # =======================================================================
    
    # These should be overloaded:
    
    def setup_channel(self, channel):
        pass
    
    def on_link(self, beacon):
        pass
    
    def on_authentication(self, beacon):
        pass
    
    def on_transport(self, beacon):
        pass
    
    # Shouldn't have to touch these:
    
    def start(self):
        self._main()

    def stop(self):
        self._node.stop()
    
    def erase(self, index):
        pass
    
    def _send_commandpipe(self, data):
        #print "send commandpipe", data
        self.upload(0xfffe, data)
    
    def _get_commandpipe(self):
        #print "get commandpipe"
        return ant.fs.commandpipe.parse(self.download(0xfffe))
    
    def create(self, typ, data, callback=None):
        #print "create", typ
        request = CreateFile(len(data), 0x80, [typ, 0x00, 0x00], [0x00, 0xff, 0xff])
        self._send_commandpipe(request.get())
        result = self._get_commandpipe()
        #result._debug()
        
        if result.get_response() != Response.Response.OK:
            raise AntFSCreateFileException("Could not create file",
                    result.get_response())
        
        #print "create result", result, result.get_index(), result.get_data_type(), result.get_identifier()
        #d = self.download_directory()
        
        self.upload(result.get_index(), data, callback)
        return result.get_index()
    
    def upload(self, index, data, callback=None):
        #print "upload", index, len(data)

        iteration = 0
        while True:
            
            # Request Upload
            
            # Continue using Last Data Offset (special MAX_ULONG value)
            request_offset = 0 if iteration == 0 else 0xffffffff
            self._send_command(UploadRequest(index, len(data), request_offset))
            
            upload_response = self._get_command()
            #upload_response._debug()
            
            if upload_response._get_argument("response") != UploadResponse.Response.OK:
                raise AntFSUploadException("Upload request failed",
                        upload_response._get_argument("response"))

            # Upload data
            offset      = upload_response._get_argument("last_data_offset")
            max_block   = upload_response._get_argument("maximum_block_size")
            #print " uploading", offset, "to", offset + max_block
            data_packet = data[offset:offset + max_block]
            crc_seed    = upload_response._get_argument("crc")
            crc_val     = crc(data_packet, upload_response._get_argument("crc"))
            
            # Pad with 0 to even 8 bytes
            missing_bytes = 8 - (len(data_packet) % 8)
            if missing_bytes != 8:
                data_packet.extend(array.array('B', [0] * missing_bytes))
                #print " adding", str(missing_bytes), "padding"

            #print " packet", len(data_packet)
            #print " crc   ", crc_val, "from seed", crc_seed

            self._send_command(UploadDataCommand(crc_seed, offset, data_packet, crc_val))
            upload_data_response = self._get_command()
            #upload_data_response._debug()
            if upload_data_response._get_argument("response") != UploadDataResponse.Response.OK:
                raise AntFSUploadException("Upload data failed",
                        upload_data_response._get_argument("response"))
            
            if callback != None and len(data) != 0:
                callback(float(offset) / float(len(data)))

            if offset + len(data_packet) >= len(data):
                #print " done"
                break

            #print " one more"
            iteration += 1

    
    def download(self, index, callback=None):
        offset  = 0
        initial = True
        crc     = 0
        data    = array.array('B')
        while True:
            _logger.debug("Download %d, o%d, c%d", index, offset, crc)
            self._send_command(DownloadRequest(index, offset, True, crc))
            _logger.debug("Wait for response...")
            try:
                response = self._get_command()
                resp = response._get_argument("response")
                if resp == DownloadResponse.Response.OK:
                    remaining    = response._get_argument("remaining")
                    offset       = response._get_argument("offset")
                    total        = offset + remaining
                    data[offset:total] = response._get_argument("data")[:remaining]
                    #print "rem", remaining, "offset", offset, "total", total, "size", response._get_argument("size")
                    # TODO: check CRC
                    
                    if callback != None and response._get_argument("size") != 0:
                        callback(float(total) / float(response._get_argument("size")))
                    if total == response._get_argument("size"):
                        return data
                    crc = response._get_argument("crc")
                    offset = total
                elif resp == DownloadResponse.Response.NOT_READABLE:
                    return data
                else:
                    raise AntFSDownloadException("Download request failed: ",
                            response._get_argument("response"))
            except Queue.Empty:
                _logger.debug("Download %d timeout", index)
                #print "recover from download failure"
    
    def download_directory(self, callback=None):
        data = self.download(0, callback)
        return Directory.parse(data)

    def link(self):
        self._channel.request_message(Message.ID.RESPONSE_CHANNEL_ID)
        self._send_command(LinkCommand(self._frequency, 4, self._serial_number))
       
        # New period, search timeout
        self._channel.set_period(4096)
        self._channel.set_search_timeout(3)
        self._channel.set_rf_freq(self._frequency)

    def authentication_serial(self):
        self._send_command(AuthenticateCommand(
                AuthenticateCommand.Request.SERIAL,
                self._serial_number))
        response = self._get_command()
        return (response.get_serial(), response.get_data_string())

    def authentication_passkey(self, passkey):
        self._send_command(AuthenticateCommand(
                AuthenticateCommand.Request.PASSKEY_EXCHANGE,
                self._serial_number, passkey))

        response = self._get_command()
        if response._get_argument("type") == AuthenticateResponse.Response.ACCEPT:
            return response.get_data_array()
        else:
            raise AntFSAuthenticationException("Passkey authentication failed",
                    response._get_argument("type"))

    def authentication_pair(self, friendly_name):
        data = array.array('B', map(ord, list(friendly_name)))
        self._send_command(AuthenticateCommand(
                AuthenticateCommand.Request.PAIRING,
                self._serial_number, data))

        response = self._get_command(30)
        if response._get_argument("type") == AuthenticateResponse.Response.ACCEPT:
            return response.get_data_array()
        else:
            raise AntFSAuthenticationException("Pair authentication failed",
                    response._get_argument("type"))
        

    def disconnect(self):
        d = DisconnectCommand(DisconnectCommand.Type.RETURN_LINK, 0, 0)
        self._send_command(d)
Esempio n. 4
0
class Application:
    _serial_number = 1337
    _frequency = 19  # 0 to 124, x - 2400 (in MHz)

    def __init__(self):

        self._queue = queue.Queue()
        self._beacons = queue.Queue()

        self._node = Node()

        try:
            NETWORK_KEY = [0xA8, 0xA4, 0x23, 0xB9, 0xF5, 0x5E, 0x63, 0xC1]
            self._node.set_network_key(0x00, NETWORK_KEY)

            print("Request basic information...")

            m = self._node.request_message(Message.ID.RESPONSE_CAPABILITIES)
            print("  Capabilities: ", m[2])

            # m = self._node.request_message(Message.ID.RESPONSE_ANT_VERSION)
            # print "  ANT version:  ", struct.unpack("<10sx", m[2])[0]

            # m = self._node.request_message(Message.ID.RESPONSE_SERIAL_NUMBER)
            # print "  Serial number:", struct.unpack("<I", m[2])[0]

            print("Starting system...")

            # NETWORK_KEY= [0xa8, 0xa4, 0x23, 0xb9, 0xf5, 0x5e, 0x63, 0xc1]
            # self._node.set_network_key(0x00, NETWORK_KEY)

            print("Key done...")

            self._channel = self._node.new_channel(
                Channel.Type.BIDIRECTIONAL_RECEIVE)
            self._channel.on_broadcast_data = self._on_data
            self._channel.on_burst_data = self._on_data

            self.setup_channel(self._channel)

            self._worker_thread = threading.Thread(target=self._worker,
                                                   name="ant.fs")
            self._worker_thread.start()
        except Exception as e:
            self.stop()
            raise e

    def _worker(self):
        self._node.start()

    def _main(self):
        try:
            _logger.debug("Link level")
            beacon = self._get_beacon()
            if self.on_link(beacon):
                for i in range(0, 5):
                    beacon = self._get_beacon()
                    if (beacon.get_client_device_state() ==
                            Beacon.ClientDeviceState.AUTHENTICATION):
                        _logger.debug("Auth layer")
                        if self.on_authentication(beacon):
                            _logger.debug("Authenticated")
                            beacon = self._get_beacon()
                            self.on_transport(beacon)
                        self.disconnect()
                        break
        finally:
            _logger.debug("Run 5")
            self.stop()

    def _on_beacon(self, data):
        b = Beacon.parse(data)
        self._beacons.put(b)

    def _on_command(self, data):
        c = ant.fs.command.parse(data)
        self._queue.put(c)

    def _on_data(self, data):
        # print "_on_data", data, len(data)
        if data[0] == 0x43:
            self._on_beacon(data[:8])
            if len(data[8:]) > 0:
                self._on_command(data[8:])
        elif data[0] == 0x44:
            self._on_command(data)

    def _get_beacon(self):
        b = self._beacons.get()
        self._beacons.task_done()
        return b

    def _get_command(self, timeout=15.0):
        _logger.debug("Get command, t%d, s%d", timeout, self._queue.qsize())
        c = self._queue.get(True, timeout)
        self._queue.task_done()
        return c

    def _send_command(self, c):
        data = c.get()
        if len(data) == 8:
            self._channel.send_acknowledged_data(data)
        else:
            self._channel.send_burst_transfer(data)

    # Application actions are defined from here
    # =======================================================================

    # These should be overloaded:

    def setup_channel(self, channel):
        pass

    def on_link(self, beacon):
        pass

    def on_authentication(self, beacon):
        pass

    def on_transport(self, beacon):
        pass

    # Shouldn't have to touch these:

    def start(self):
        self._main()

    def stop(self):
        self._node.stop()

    def _send_commandpipe(self, data):
        # print "send commandpipe", data
        self.upload(0xFFFE, data)

    def _get_commandpipe(self):
        # print "get commandpipe"
        return ant.fs.commandpipe.parse(self.download(0xFFFE))

    def create(self, typ, data, callback=None):
        # print "create", typ
        request = CreateFile(len(data), 0x80, [typ, 0x00, 0x00],
                             [0x00, 0xFF, 0xFF])
        self._send_commandpipe(request.get())
        result = self._get_commandpipe()
        # result._debug()

        if result.get_response() != Response.Response.OK:
            raise AntFSCreateFileException("Could not create file",
                                           result.get_response())

        # print "create result", result, result.get_index(), result.get_data_type(), result.get_identifier()
        # d = self.download_directory()

        # Inform the application that the upload request was successfully created
        if callback is not None:
            callback(0)

        self.upload(result.get_index(), data, callback)
        return result.get_index()

    def upload(self, index, data, callback=None):
        # print "upload", index, len(data)

        iteration = 0
        while True:

            # Request Upload

            # Continue using Last Data Offset (special MAX_ULONG value)
            request_offset = 0 if iteration == 0 else 0xFFFFFFFF
            self._send_command(UploadRequest(index, len(data), request_offset))

            upload_response = self._get_command()
            # upload_response._debug()

            if upload_response._get_argument(
                    "response") != UploadResponse.Response.OK:
                raise AntFSUploadException(
                    "Upload request failed",
                    upload_response._get_argument("response"))

            # Upload data
            offset = upload_response._get_argument("last_data_offset")
            max_block = upload_response._get_argument("maximum_block_size")
            # print " uploading", offset, "to", offset + max_block
            data_packet = data[offset:offset + max_block]
            crc_seed = upload_response._get_argument("crc")
            crc_val = crc(data_packet, upload_response._get_argument("crc"))

            # Pad with 0 to even 8 bytes
            missing_bytes = 8 - (len(data_packet) % 8)
            if missing_bytes != 8:
                data_packet.extend(array.array("B", [0] * missing_bytes))
                # print " adding", str(missing_bytes), "padding"

            # print " packet", len(data_packet)
            # print " crc   ", crc_val, "from seed", crc_seed

            self._send_command(
                UploadDataCommand(crc_seed, offset, data_packet, crc_val))
            upload_data_response = self._get_command()
            # upload_data_response._debug()
            if (upload_data_response._get_argument("response") !=
                    UploadDataResponse.Response.OK):
                raise AntFSUploadException(
                    "Upload data failed",
                    upload_data_response._get_argument("response"))

            if callback is not None and len(data) != 0:
                callback((offset + len(data_packet)) / len(data))

            if offset + len(data_packet) >= len(data):
                # print " done"
                break

            # print " one more"
            iteration += 1

    def download(self, index, callback=None):
        offset = 0
        initial = True
        crc = 0
        data = array.array("B")
        while True:
            _logger.debug("Download %d, o%d, c%d", index, offset, crc)
            self._send_command(DownloadRequest(index, offset, True, crc))
            _logger.debug("Wait for response...")
            try:
                response = self._get_command()
                if response._get_argument(
                        "response") == DownloadResponse.Response.OK:
                    remaining = response._get_argument("remaining")
                    offset = response._get_argument("offset")
                    total = offset + remaining
                    data[offset:total] = response._get_argument(
                        "data")[:remaining]
                    # print "rem", remaining, "offset", offset, "total", total, "size", response._get_argument("size")
                    # TODO: check CRC

                    if callback is not None and response._get_argument(
                            "size") != 0:
                        callback(total / response._get_argument("size"))
                    if total == response._get_argument("size"):
                        return data
                    crc = response._get_argument("crc")
                    offset = total
                else:
                    raise AntFSDownloadException(
                        "Download request failed: ",
                        response._get_argument("response"))
            except queue.Empty:
                _logger.debug("Download %d timeout", index)
                # print "recover from download failure"

    def download_directory(self, callback=None):
        data = self.download(0, callback)
        return Directory.parse(data)

    def set_time(self, time=datetime.datetime.utcnow()):
        """
        :param time: datetime in UTC, or None to set to current time
        """
        utc_tai_diff_seconds = 35
        offset = time - datetime.datetime(1989, 12, 31, 0, 0, 0)
        t = Time(
            int(offset.total_seconds()) + utc_tai_diff_seconds, 0xFFFFFFFF, 0)
        self._send_commandpipe(t.get())

        result = self._get_commandpipe()

        if result.get_response() != TimeResponse.Response.OK:
            raise AntFSTimeException("Failed to set time",
                                     result.get_response())

    def erase(self, index):
        self._send_command(EraseRequestCommand(index))
        response = self._get_command()

        if (response._get_argument("response") !=
                EraseResponse.Response.ERASE_SUCCESSFUL):
            raise AntFSDownloadException("Erase request failed: ",
                                         response._get_argument("response"))

    def link(self):
        self._channel.request_message(Message.ID.RESPONSE_CHANNEL_ID)
        self._send_command(LinkCommand(self._frequency, 4,
                                       self._serial_number))

        # New period, search timeout
        self._channel.set_period(4096)
        self._channel.set_search_timeout(10)
        self._channel.set_rf_freq(self._frequency)

    def authentication_serial(self):
        self._send_command(
            AuthenticateCommand(AuthenticateCommand.Request.SERIAL,
                                self._serial_number))
        response = self._get_command()
        return (response.get_serial(), response.get_data_string())

    def authentication_passkey(self, passkey):
        self._send_command(
            AuthenticateCommand(
                AuthenticateCommand.Request.PASSKEY_EXCHANGE,
                self._serial_number,
                passkey,
            ))

        response = self._get_command()
        if response._get_argument(
                "type") == AuthenticateResponse.Response.ACCEPT:
            return response.get_data_array()
        else:
            raise AntFSAuthenticationException("Passkey authentication failed",
                                               response._get_argument("type"))

    def authentication_pair(self, friendly_name):
        data = array.array("B", map(ord, list(friendly_name)))
        self._send_command(
            AuthenticateCommand(AuthenticateCommand.Request.PAIRING,
                                self._serial_number, data))

        response = self._get_command(30)
        if response._get_argument(
                "type") == AuthenticateResponse.Response.ACCEPT:
            return response.get_data_array()
        else:
            raise AntFSAuthenticationException("Pair authentication failed",
                                               response._get_argument("type"))

    def disconnect(self):
        d = DisconnectCommand(DisconnectCommand.Type.RETURN_LINK, 0, 0)
        self._send_command(d)
class Application:
    
    _serial_number = 1337
    _frequency     = 19    # 0 to 124, x - 2400 (in MHz)
    
    def __init__(self):

        self._queue = Queue.Queue()
        self._beacons = Queue.Queue()

        self._node = Node(0x0fcf, 0x1008)

        print "Request basic information..."
        m = self._node.request_message(Message.ID.RESPONSE_VERSION)
        print "  ANT version:  ", struct.unpack("<10sx", m[2])[0]
        m = self._node.request_message(Message.ID.RESPONSE_CAPABILITIES)
        print "  Capabilities: ", m[2]
        m = self._node.request_message(Message.ID.RESPONSE_SERIAL_NUMBER)
        print "  Serial number:", struct.unpack("<I", m[2])[0]

        print "Starting system..."

        NETWORK_KEY= [0xa8, 0xa4, 0x23, 0xb9, 0xf5, 0x5e, 0x63, 0xc1]

        self._node.reset_system()
        self._node.set_network_key(0x00, NETWORK_KEY)

        self._channel = self._node.new_channel(Channel.Type.BIDIRECTIONAL_RECEIVE)
        self._channel.on_broadcast_data = self._on_data
        self._channel.on_burst_data = self._on_data
        
        self.setup_channel(self._channel)
        
        self._worker_thread =threading.Thread(target=self._worker, name="ant.fs")
        self._worker_thread.start()

    def _worker(self):
        self._node.start()

    def _main(self):
        try:
            _logger.debug("Link level")
            beacon = self._get_beacon()
            if self.on_link(beacon):
                for i in range(0, 5):
                    beacon = self._get_beacon()
                    if beacon.get_client_device_state() == Beacon.ClientDeviceState.AUTHENTICATION:
                        _logger.debug("Auth layer")
                        if self.on_authentication(beacon):
                            _logger.debug("Authenticated")
                            beacon = self._get_beacon()
                            self.on_transport(beacon)
                        self.disconnect()
                        break
        except Exception as e:
            print e
            for line in traceback.format_exc().splitlines():
                _logger.error("%r", line)
        finally:
            _logger.debug("Run 5")
            self.stop()


    def _on_beacon(self, data):
        b = Beacon.parse(data)
        self._beacons.put(b)

    def _on_command(self, data):
        c = ant.fs.command.parse(data)
        self._queue.put(c)

    def _on_data(self, data):
        #print "_on_data", data, len(data)
        if data[0] == 0x43:
            self._on_beacon(data[:8])
            if len(data[8:]) > 0:
                self._on_command(data[8:])
        elif data[0] == 0x44:
            self._on_command(data)
    
    def _get_beacon(self):
        b = self._beacons.get()
        self._beacons.task_done()
        return b
    
    def _get_command(self, timeout=3.0):
        _logger.debug("Get command, t%d, s%d", timeout, self._queue.qsize())
        c = self._queue.get(True, timeout)
        self._queue.task_done()
        return c
    
    def _send_command(self, c):
        data = c.get()
        if len(data) == 8:
            self._channel.send_acknowledged_data(data)
        else:
            self._channel.send_burst_transfer(data)
    
    # Application actions are defined from here
    # =======================================================================
    
    # These should be overloaded:
    
    def setup_channel(self, channel):
        pass
    
    def on_link(self, beacon):
        pass
    
    def on_authentication(self, beacon):
        pass
    
    def on_transport(self, beacon):
        pass
    
    # Shouldn't have to touch these:
    
    def start(self):
        self._main()

    def stop(self):
        self._node.stop()
    
    def erase(self, index):
        pass
    
    def upload(self, index, data):
        pass
    
    def download(self, index, callback=None):
        offset  = 0
        initial = True
        crc     = 0
        data    = array.array('B')
        while True:
            _logger.debug("Download %d, o%d, c%d", index, offset, crc)
            self._send_command(DownloadRequest(index, offset, True, crc))
            _logger.debug("Wait for response...")
            try:
                response = self._get_command()
                if response._get_argument("response") == DownloadResponse.Response.OK:
                    remaining    = response._get_argument("remaining")
                    offset       = response._get_argument("offset")
                    total        = offset + remaining
                    data[offset:total] = response._get_argument("data")[:remaining]
                    #print "rem", remaining, "offset", offset, "total", total, "size", response._get_argument("size")
                    if callback != None:
                        callback(float(total) / float(response._get_argument("size")))
                    if total == response._get_argument("size"):
                        return data
                    crc = response._get_argument("crc")
                    offset = total
                else:
                    raise AntFSDownloadException(response._get_argument("response"))
            except Queue.Empty:
                _logger.debug("Download %d timeout", index)
                #print "recover from download failure"
    
    def download_directory(self, callback=None):
        data = self.download(0, callback)
        return Directory.parse(data)

    def link(self):
        self._channel.request_message(Message.ID.RESPONSE_CHANNEL_ID)
        self._send_command(LinkCommand(self._frequency, 4, self._serial_number))
       
        # New period, search timeout
        self._channel.set_period(4096)
        self._channel.set_search_timeout(3)
        self._channel.set_rf_freq(self._frequency)

    def authentication_serial(self):
        self._send_command(AuthenticateCommand(
                AuthenticateCommand.Request.SERIAL,
                self._serial_number))
        response = self._get_command()
        return (response.get_serial(), response.get_data_string())

    def authentication_passkey(self, passkey):
        self._send_command(AuthenticateCommand(
                AuthenticateCommand.Request.PASSKEY_EXCHANGE,
                self._serial_number, passkey))

        response = self._get_command()
        if response._get_argument("type") == AuthenticateResponse.Response.ACCEPT:
            return response.get_data_array()
        else:
            raise AntFSAuthenticationException(response._get_argument("type"))

    def authentication_pair(self, friendly_name):
        data = array.array('B', map(ord, list(friendly_name)))
        self._send_command(AuthenticateCommand(
                AuthenticateCommand.Request.PAIRING,
                self._serial_number, data))

        response = self._get_command(30)
        if response._get_argument("type") == AuthenticateResponse.Response.ACCEPT:
            return response.get_data_array()
        else:
            raise AntFSAuthenticationException(response._get_argument("type"))
        

    def disconnect(self):
        d = DisconnectCommand(DisconnectCommand.Type.RETURN_LINK, 0, 0)
        self._send_command(d)
Esempio n. 6
0
class AntPlusNode:
    def __init__(self, network_key):
        self.node = Node()
        self.node.set_network_key(0x00, network_key)
        self.ant_device_id = 1

    def attach_hrm(self, device_number=0, transfer_type=0):
        channel = self.node.new_channel(Channel.Type.BIDIRECTIONAL_RECEIVE)
        hrm = AntPlusHRM(channel,
                         device_number=device_number,
                         transfer_type=transfer_type)
        channel.open()
        return hrm

    def attach_power_meter(self, device_number=0, transfer_type=0):
        channel = self.node.new_channel(Channel.Type.BIDIRECTIONAL_RECEIVE)
        pwr_meter = AntPlusPowerMeter(channel,
                                      device_number=device_number,
                                      transfer_type=transfer_type)
        pwr_meter._ant_device_id = self.check_id_of_power_meter(
        )  #id checked once at creation of pwr_meter
        channel.open()
        return pwr_meter

    def attach_speed_sensor(self,
                            wheel_circumference_meters,
                            device_number=0,
                            transfer_type=0):
        channel = self.node.new_channel(Channel.Type.BIDIRECTIONAL_RECEIVE)
        sensor = AntPlusSpeedSensor(
            channel,
            wheel_circumference_meters=wheel_circumference_meters,
            device_number=device_number,
            transfer_type=transfer_type)
        channel.open()
        return sensor

    def attach_cadence_sensor(self, device_number=0, transfer_type=0):
        channel = self.node.new_channel(Channel.Type.BIDIRECTIONAL_RECEIVE)
        sensor = AntPlusCadenceSensor(channel,
                                      device_number=device_number,
                                      transfer_type=transfer_type)
        channel.open()
        return sensor

    def attach_speed_and_cadence_sensor(self,
                                        wheel_circumference_meters,
                                        device_number=0,
                                        transfer_type=0):
        channel = self.node.new_channel(Channel.Type.BIDIRECTIONAL_RECEIVE)
        sensor = AntPlusSpeedAndCadenceSensor(
            channel,
            wheel_circumference_meters=wheel_circumference_meters,
            device_number=device_number,
            transfer_type=transfer_type)
        channel.open()
        return sensor

    def attach_combined_speed_and_cadence_sensor(self,
                                                 wheel_circumference_meters,
                                                 speed_device_number=0,
                                                 speed_transfer_type=0,
                                                 cadence_device_number=0,
                                                 cadence_transfer_type=0):
        channel1 = self.node.new_channel(Channel.Type.BIDIRECTIONAL_RECEIVE)
        channel2 = self.node.new_channel(Channel.Type.BIDIRECTIONAL_RECEIVE)
        sensor = AntPlusCombinedSpeedAndCadenceSensors(
            channel1,
            channel2,
            wheel_circumference_meters=wheel_circumference_meters,
            speed_device_number=speed_device_number,
            speed_transfer_type=speed_transfer_type,
            cadence_device_number=cadence_device_number,
            cadence_transfer_type=cadence_transfer_type)
        channel1.open()
        channel2.open()
        return sensor

    def check_id_of_power_meter(self, device_number=0, transfer_type=0):
        meter_id = self.node.request_message(Message.ID.RESPONSE_CHANNEL_ID)
        return meter_id

    def start(self):
        self.node.start()

    def stop(self):
        self.node.stop()
Esempio n. 7
0
File: manager.py Progetto: La0/GFrun
class Application:

    _serial_number = 1337
    _frequency = 19  # 0 to 124, x - 2400 (in MHz)

    def __init__(self):

        self._queue = Queue.Queue()
        self._beacons = Queue.Queue()

        self._node = Node(0x0fcf, 0x1008)

        print "Request basic information..."
        m = self._node.request_message(Message.ID.RESPONSE_VERSION)
        print "  ANT version:  ", struct.unpack("<10sx", m[2])[0]
        m = self._node.request_message(Message.ID.RESPONSE_CAPABILITIES)
        print "  Capabilities: ", m[2]
        m = self._node.request_message(Message.ID.RESPONSE_SERIAL_NUMBER)
        print "  Serial number:", struct.unpack("<I", m[2])[0]

        print "Starting system..."

        NETWORK_KEY = [0xa8, 0xa4, 0x23, 0xb9, 0xf5, 0x5e, 0x63, 0xc1]

        self._node.reset_system()
        self._node.set_network_key(0x00, NETWORK_KEY)

        self._channel = self._node.new_channel(
            Channel.Type.BIDIRECTIONAL_RECEIVE)
        self._channel.on_broadcast_data = self._on_data
        self._channel.on_burst_data = self._on_data

        self.setup_channel(self._channel)

        self._worker_thread = threading.Thread(target=self._worker,
                                               name="ant.fs")
        self._worker_thread.start()

    def _worker(self):
        self._node.start()

    def _main(self):
        try:
            _logger.debug("Link level")
            beacon = self._get_beacon()
            if self.on_link(beacon):
                for i in range(0, 5):
                    beacon = self._get_beacon()
                    if beacon.get_client_device_state(
                    ) == Beacon.ClientDeviceState.AUTHENTICATION:
                        _logger.debug("Auth layer")
                        if self.on_authentication(beacon):
                            _logger.debug("Authenticated")
                            beacon = self._get_beacon()
                            self.on_transport(beacon)
                        self.disconnect()
                        break
        except Exception as e:
            print e
            for line in traceback.format_exc().splitlines():
                _logger.error("%r", line)
        finally:
            _logger.debug("Run 5")
            self.stop()

    def _on_beacon(self, data):
        b = Beacon.parse(data)
        self._beacons.put(b)

    def _on_command(self, data):
        c = ant.fs.command.parse(data)
        self._queue.put(c)

    def _on_data(self, data):
        #print "_on_data", data, len(data)
        if data[0] == 0x43:
            self._on_beacon(data[:8])
            if len(data[8:]) > 0:
                self._on_command(data[8:])
        elif data[0] == 0x44:
            self._on_command(data)

    def _get_beacon(self):
        b = self._beacons.get()
        self._beacons.task_done()
        return b

    def _get_command(self, timeout=3.0):
        _logger.debug("Get command, t%d, s%d", timeout, self._queue.qsize())
        c = self._queue.get(True, timeout)
        self._queue.task_done()
        return c

    def _send_command(self, c):
        data = c.get()
        if len(data) == 8:
            self._channel.send_acknowledged_data(data)
        else:
            self._channel.send_burst_transfer(data)

    # Application actions are defined from here
    # =======================================================================

    # These should be overloaded:

    def setup_channel(self, channel):
        pass

    def on_link(self, beacon):
        pass

    def on_authentication(self, beacon):
        pass

    def on_transport(self, beacon):
        pass

    # Shouldn't have to touch these:

    def start(self):
        self._main()

    def stop(self):
        self._node.stop()

    def erase(self, index):
        pass

    def upload(self, index, data):
        pass

    def download(self, index, callback=None):
        offset = 0
        initial = True
        crc = 0
        data = array.array('B')
        while True:
            _logger.debug("Download %d, o%d, c%d", index, offset, crc)
            self._send_command(DownloadRequest(index, offset, True, crc))
            _logger.debug("Wait for response...")
            try:
                response = self._get_command()
                if response._get_argument(
                        "response") == DownloadResponse.Response.OK:
                    remaining = response._get_argument("remaining")
                    offset = response._get_argument("offset")
                    total = offset + remaining
                    data[offset:total] = response._get_argument(
                        "data")[:remaining]
                    #print "rem", remaining, "offset", offset, "total", total, "size", response._get_argument("size")
                    if callback != None:
                        callback(
                            float(total) /
                            float(response._get_argument("size")))
                    if total == response._get_argument("size"):
                        return data
                    crc = response._get_argument("crc")
                    offset = total
                else:
                    raise AntFSDownloadException(
                        response._get_argument("response"))
            except Queue.Empty:
                _logger.debug("Download %d timeout", index)
                #print "recover from download failure"

    def download_directory(self, callback=None):
        data = self.download(0, callback)
        return Directory.parse(data)

    def link(self):
        self._channel.request_message(Message.ID.RESPONSE_CHANNEL_ID)
        self._send_command(LinkCommand(self._frequency, 4,
                                       self._serial_number))

        # New period, search timeout
        self._channel.set_period(4096)
        self._channel.set_search_timeout(3)
        self._channel.set_rf_freq(self._frequency)

    def authentication_serial(self):
        self._send_command(
            AuthenticateCommand(AuthenticateCommand.Request.SERIAL,
                                self._serial_number))
        response = self._get_command()
        return (response.get_serial(), response.get_data_string())

    def authentication_passkey(self, passkey):
        self._send_command(
            AuthenticateCommand(AuthenticateCommand.Request.PASSKEY_EXCHANGE,
                                self._serial_number, passkey))

        response = self._get_command()
        if response._get_argument(
                "type") == AuthenticateResponse.Response.ACCEPT:
            return response.get_data_array()
        else:
            raise AntFSAuthenticationException(response._get_argument("type"))

    def authentication_pair(self, friendly_name):
        data = array.array('B', map(ord, list(friendly_name)))
        self._send_command(
            AuthenticateCommand(AuthenticateCommand.Request.PAIRING,
                                self._serial_number, data))

        response = self._get_command(30)
        if response._get_argument(
                "type") == AuthenticateResponse.Response.ACCEPT:
            return response.get_data_array()
        else:
            raise AntFSAuthenticationException(response._get_argument("type"))

    def disconnect(self):
        d = DisconnectCommand(DisconnectCommand.Type.RETURN_LINK, 0, 0)
        self._send_command(d)