def start_reading(self):
        readBuffer = UartReadBuffer()
        self.started = True
        _LOGGER.debug(F"Read starting on serial port.{self.port} {self.running}")
        try:
            while self.running:
                bytesFromSerial = self.serialController.read()
                if bytesFromSerial:
                    # clear out the entire read buffer
                    if self.serialController.in_waiting > 0:
                        additionalBytes = self.serialController.read(self.serialController.in_waiting)
                        bytesFromSerial = bytesFromSerial + additionalBytes
                    readBuffer.addByteArray(bytesFromSerial)

            # print("Cleaning up UartBridge")
        except OSError or serial.SerialException:
            _LOGGER.info("Connection to USB Failed. Retrying...")
        except KeyboardInterrupt:
            self.running = False
            _LOGGER.debug("Closing serial connection.")

        # close the serial controller
        self.serialController.close()
        self.serialController = None
        # remove the event listener pointing to the old connection
        UartEventBus.unsubscribe(self.eventId)
        self.started = False
        UartEventBus.emit(SystemTopics.connectionClosed, True)
Esempio n. 2
0
    def initialize_usb_sync(self,
                            port=None,
                            baudrate=230400,
                            writeChunkMaxSize=0):
        '''
                writing in chunks solves issues writing to certain JLink chips. A max chunkSize of 64 was found to work well for our case.
                For normal usage with Crownstones this is not required.
                writeChunkMaxSize of 0 will not send the payload in chunks
                :param port:
                :param baudrate:
                :param writeChunkMaxSize:
                :return:
                '''
        self.uartManager.config(port, baudrate, writeChunkMaxSize)

        result = [False]

        def handleMessage(result, data):
            result[0] = True

        event = UartEventBus.subscribe(
            SystemTopics.connectionEstablished,
            lambda data: handleMessage(result, data))
        self.uartManager.start()

        try:
            while not result[0] and self.running:
                time.sleep(0.1)
        except KeyboardInterrupt:
            print("\nClosing Crownstone Uart.... Thanks for your time!")
            self.stop()

        UartEventBus.unsubscribe(event)
    def parse(self, wrapperPacket: UartWrapperPacket):
        """
        Callback for SystemTopics.uartNewPackage, emits a message of type SystemTopic.uartNewMessage
        if the received message was of the correct protocol version and unencrypted.
        :param wrapperPacket:
        :return:
        """
        if type(wrapperPacket) is not UartWrapperPacket:
            raise TypeError

        if wrapperPacket.protocolMajor != PROTOCOL_MAJOR:
            _LOGGER.warning(
                F"Unknown protocol: {wrapperPacket.protocolMajor}.{wrapperPacket.protocolMinor}"
            )
            return

        msgType = wrapperPacket.messageType
        if msgType == UartMessageType.UART_MESSAGE:
            uartMsg = UartMessagePacket()
            if uartMsg.parse(wrapperPacket.payload):
                UartEventBus.emit(SystemTopics.uartNewMessage, uartMsg)
        elif msgType == UartMessageType.ENCRYPTED_UART_MESSAGE:
            _LOGGER.info(
                f"Received encrypted msg: decryption is not implemented.")
            return
        else:
            _LOGGER.warning(F"Unknown message type: {msgType}")
            return
Esempio n. 4
0
    def _switch_crownstone(self, crownstone_id: int, switch_val: int):
        """
        :param crownstone_id:
        :param switch_val: 0% .. 100% or special value (SwitchValSpecial).
        :return:
        """

        # create a stone switch state packet to go into the multi switch
        stoneSwitchPacket = StoneMultiSwitchPacket(crownstone_id, switch_val)

        # wrap it in a mesh multi switch packet
        meshMultiSwitchPacket = MeshMultiSwitchPacket([stoneSwitchPacket
                                                       ]).getPacket()

        # wrap that in a control packet
        controlPacket = ControlPacket(ControlType.MULTISWITCH).loadByteArray(
            meshMultiSwitchPacket).getPacket()

        # wrap that in a uart message
        uartMessage = UartMessagePacket(UartTxType.CONTROL,
                                        controlPacket).getPacket()

        # finally wrap it in a uart wrapper packet
        uartPacket = UartWrapperPacket(UartMessageType.UART_MESSAGE,
                                       uartMessage).getPacket()

        # send over uart
        UartEventBus.emit(SystemTopics.uartWriteData, uartPacket)
    def process(self):
        """
        Process a buffer.

        Check CRC, and emit a uart packet.

        Buffer starts after size header, and includes wrapper header and tail (CRC).

        Return: processing success
        """

        # Check size
        bufferSize = len(self.buffer)
        wrapperSize = WRAPPER_HEADER_SIZE + CRC_SIZE
        if bufferSize < wrapperSize:
            _LOGGER.warning("Buffer too small")
            return False

        # Get the buffer between size field and CRC:
        baseBuffer = self.buffer[0 : bufferSize - CRC_SIZE]

        # Check CRC
        calculatedCrc = crc16ccitt(baseBuffer)
        sourceCrc = Conversion.uint8_array_to_uint16(self.buffer[bufferSize - CRC_SIZE : ])

        if calculatedCrc != sourceCrc:
            _LOGGER.warning("Failed CRC: {0} != {1} (data: {2})".format(calculatedCrc, sourceCrc, baseBuffer))
            UartEventBus.emit(DevTopics.uartNoise, "crc mismatch")
            return False

        wrapperPacket = UartWrapperPacket()
        if wrapperPacket.parse(baseBuffer):
            UartEventBus.emit(SystemTopics.uartNewPackage, wrapperPacket)
            return True
Esempio n. 6
0
    async def _command_via_mesh_broadcast(self, packet: bytearray):
        # this is only for time and noop
        # broadcast to all:
        # value: 1
        corePacket = MeshBroadcastPacket(packet).getPacket()
        controlPacket = ControlPacket(
            ControlType.MESH_COMMAND).loadByteArray(corePacket).getPacket()
        uartMessage = UartMessagePacket(UartTxType.CONTROL,
                                        controlPacket).getPacket()
        uartPacket = UartWrapperPacket(UartMessageType.UART_MESSAGE,
                                       uartMessage).getPacket()

        resultCollector = Collector(timeout=2, topic=SystemTopics.resultPacket)

        # send the message to the Crownstone
        UartEventBus.emit(SystemTopics.uartWriteData, uartPacket)

        # wait for the collectors to fill
        commandResultData = await resultCollector.receive()

        if commandResultData is not None:
            if commandResultData.resultCode is ResultValue.BUSY:
                await asyncio.sleep(0.2)
                return await self._command_via_mesh_broadcast(packet)
            elif commandResultData.resultCode is not ResultValue.SUCCESS:
                raise CrownstoneException(commandResultData.resultCode,
                                          "Command has failed.")

        await asyncio.sleep(0.1)
    def write_with_result_sync(self, success_codes : List[ResultValue]=None, result_timeout=0.25) -> ResultPacket:
        """
        write_with_result_sync will take the data packet you have provided to the constructor and send it over UART.
        It will wait for an incoming result packet and return it once it has been received.

        You can optionally provide a list of ResultValue result codes. If the list is empty [] all resultPackets will be returned.
        Otherwise it will use your provided list to filter on. If you leave it None, we will default to ResultValue.SUCCESS.

        If a resultcode is not in the list, an CrownstoneException will be raised. This method is blocking.
        If the write fails, an CrownstoneException will be raised.
        :return:

        :param success_codes: List[ResultValue]
        :param result_timeout: time to wait on a result in seconds before raising a timeout error. This should be higher than the UART_WRITE_TIMEOUT
        :return: ResultPacket
        """
        if success_codes is None:
            success_codes = [ResultValue.SUCCESS]
        UartEventBus.emit(SystemTopics.uartWriteData, self.dataToSend)
        counter = 0
        while counter < result_timeout:
            if self.result:
                return self._checkResult(success_codes)

            time.sleep(self.interval)
            counter += self.interval

        self._wrapUpFailedResult(result_timeout)
Esempio n. 8
0
    def write_to_uart(self, data):
        _LOGGER.debug(f"write_to_uart: {data}")
        if self.serialController is not None and self.started:
            try:
                if self.writeChunkMaxSize == 0:
                    self.serialController.write(data)
                else:
                    # writing in chunks solves issues writing to certain JLink chips. A max chunkSize of 64 was found to work well for our case.
                    chunkSize = self.writeChunkMaxSize
                    index = 0
                    while (index*chunkSize) < len(data):
                        chunkedData = data[index*chunkSize:chunkSize*(index+1)]
                        index += 1
                        self.serialController.write(chunkedData)

                UartEventBus.emit(SystemTopics.uartWriteSuccess, data)
            except serial.SerialTimeoutException as e:
                UartEventBus.emit(SystemTopics.uartWriteError, {"message":"Timeout on uart write.", "error": e})
            except serial.SerialException as e:
                UartEventBus.emit(SystemTopics.uartWriteError, {"message":"SerialException occurred during uart write", "error": e})
            except OSError as e:
                UartEventBus.emit(SystemTopics.uartWriteError, {"message":"OSError occurred during uart write.", "error": e})
            except:
                e = sys.exc_info()[0]
                UartEventBus.emit(SystemTopics.uartWriteError, {"message":"Unknown error during uart write.", "error": e})
        else:
            self.stop()
Esempio n. 9
0
 def writeHello(self):
     helloPacket = UartCommandHelloPacket().getPacket()
     uartMessage = UartMessagePacket(UartTxType.HELLO,
                                     helloPacket).getPacket()
     uartPacket = UartWrapperPacket(UartMessageType.UART_MESSAGE,
                                    uartMessage).getPacket()
     UartEventBus.emit(SystemTopics.uartWriteData, uartPacket)
Esempio n. 10
0
 def echo(self, string):
     controlPacket = ControlPacket(
         ControlType.UART_MESSAGE).loadString(string).getPacket()
     uartMessage = UartMessagePacket(UartTxType.CONTROL,
                                     controlPacket).getPacket()
     uartPacket = UartWrapperPacket(UartMessageType.UART_MESSAGE,
                                    uartMessage).getPacket()
     UartEventBus.emit(SystemTopics.uartWriteData, uartPacket)
Esempio n. 11
0
    def add(self, byte):
        # An escape shouldn't be followed by a special byte.
        if self.escapingNextByte and (byte is START_TOKEN
                                      or byte is ESCAPE_TOKEN):
            _LOGGER.warning("Special byte after escape token")
            UartEventBus.emit(DevTopics.uartNoise,
                              "special byte after escape token")
            self.reset()
            return

        # Activate on start token.
        if byte is START_TOKEN:
            if self.active:
                _LOGGER.warning("MULTIPLE START TOKENS")
                _LOGGER.debug(
                    f"Multiple start tokens: sizeToRead={self.sizeToRead} bufLen={len(self.buffer)} buffer={self.buffer}"
                )
                UartEventBus.emit(DevTopics.uartNoise, "multiple start token")
            self.reset()
            self.active = True
            return

        if not self.active:
            return

        # Escape next byte on escape token.
        if byte is ESCAPE_TOKEN:
            self.escapingNextByte = True
            return

        if self.escapingNextByte:
            byte ^= BIT_FLIP_MASK
            self.escapingNextByte = False

        self.buffer.append(byte)
        bufferSize = len(self.buffer)

        if self.sizeToRead == 0:
            # We didn't parse the size yet.
            if bufferSize == SIZE_HEADER_SIZE:
                # Now we know the remaining size to read
                self.sizeToRead = Conversion.uint8_array_to_uint16(self.buffer)

                # Size to read shouldn't be 0.
                if self.sizeToRead == 0:
                    self.reset()
                    return

                self.buffer = []
                return

        elif bufferSize >= self.sizeToRead:
            self.process()
            self.reset()
            return
Esempio n. 12
0
    def handleStateUpdate(self, data):
        stoneId = data[0]
        advPayload = data[1]

        if stoneId in self.stones:
            if hasattr(advPayload, 'timestamp'):
                if self.stones[stoneId].timestamp < advPayload.timestamp:
                    self.stones[stoneId] = advPayload
                    self.emitNewData(advPayload)
        else:
            UartEventBus.emit(SystemTopics.newCrownstoneFound, stoneId)
            self.stones[stoneId] = advPayload
            self.emitNewData(advPayload)
    def receive_sync(self):
        counter = 0
        while counter < self.timeout:
            if self.response is not None:
                # cleanup the listener(s)
                UartEventBus.unsubscribe(self.cleanupId)
                return self.response

            time.sleep(self.interval)
            counter += self.interval

        UartEventBus.unsubscribe(self.cleanupId)
        return None
    def setupConnection(self, port, performHandshake=True):
        _LOGGER.debug(F"Setting up connection... port={port} baudRate={self.baudRate} performHandshake={performHandshake}")
        bridge_exception_queue = queue.Queue()
        self._uartBridge = UartBridge(bridge_exception_queue, port, self.baudRate, self.writeChunkMaxSize)
        self._uartBridge.start()

        def initialize_bridge():
            # handle exceptions that happen in thread while initializing
            while not self._uartBridge.started and self.running:
                try:
                    exception, exception_value, trace = bridge_exception_queue.get(block=False)
                    self._uartBridge.join()
                    raise exception(exception_value)
                except queue.Empty:
                    pass
                    
                time.sleep(0.1)
        
        # attempt serial connection with the dongle
        initialize_bridge()

        # this is true by default if no handshake is required
        handshake_succesfull = True

        if performHandshake:
            collector = Collector(timeout=0.25, topic=UartTopics.hello)
            self.writeHello()
            reply = collector.receive_sync()

            handshake_succesfull = False
            if isinstance(reply, UartCrownstoneHelloPacket):
                handshake_succesfull = True
                _LOGGER.debug("Handshake successful")
            else:
                if self.port == port:
                    _LOGGER.warning("Handshake failed: no reply from the crownstone.")
                else:
                    _LOGGER.debug("Handshake failed: no reply from the crownstone.")

        if not handshake_succesfull:
            _LOGGER.debug("Reinitialization required")
            self._attemptingIndex += 1
            self._uartBridge.stop()

            initialize_bridge()

        else:
            _LOGGER.info("Connection established to {}".format(port))
            self.port = port
            self.ready = True
            UartEventBus.emit(SystemTopics.connectionEstablished)
    def reset(self, discarded=False):
        """
        Resets to initial state, emitting uartDiscardedData if necessary.

        :param discarded: True when reset due to discarded data.
        """
        if discarded and len(self.rawBuffer):
            UartEventBus.emit(SystemTopics.uartDiscardedData, self.rawBuffer)

        self.rawBuffer = []
        self.buffer = []
        self.escapingNextByte = False
        self.active = False
        self.sizeToRead = 0
    def __init__(self, dataToSend: List[int], interval = 0.001):
        """
        This class will handle the event flow around writing to uart and receiving errors or result codes.
        :param dataToSend: This is your data packet
        :param interval: Polling interval. Don't touch. This is cheap and local only. It does not do uart things.
        """
        self.dataToSend : List[int] = dataToSend
        self.interval = interval

        self.error   = None
        self.success = False
        self.result  = None

        self.cleanupIds = []
        self.cleanupIds.append(UartEventBus.subscribe(SystemTopics.resultPacket,     self._handleResult))
        self.cleanupIds.append(UartEventBus.subscribe(SystemTopics.uartWriteSuccess, self._handleSuccess))
        self.cleanupIds.append(UartEventBus.subscribe(SystemTopics.uartWriteError,   self._handleError))
    def __init__(self, topic=None, timeout=10, interval=0.05):
        self.response = None
        self.timeout = timeout
        self.interval = interval

        self.cleanupId = None
        if topic is not None:
            self.cleanupId = UartEventBus.subscribe(topic, self.collect)
    def write_sync(self) -> True:
        """
        write_sync will take the data packet you have provided to the constructor and send it over UART.
        This method is blocking. If the write fails, an CrownstoneException will be raised.
        :return:
        """

        UartEventBus.emit(SystemTopics.uartWriteData, self.dataToSend)
        counter = 0
        while counter < 2 * UART_WRITE_TIMEOUT:
            if self.success:
                # cleanup the listener(s)
                self.__del__()
                return True

            time.sleep(self.interval)
            counter += self.interval
        self._wrapUpFailedWrite()
Esempio n. 19
0
    def setupConnection(self, port, performHandshake=True):
        _LOGGER.debug(
            F"Setting up connection... port={port} baudRate={self.baudRate} performHandshake={performHandshake}"
        )
        self._uartBridge = UartBridge(port, self.baudRate,
                                      self.writeChunkMaxSize)
        self._uartBridge.start()

        # wait for the bridge to initialize
        while not self._uartBridge.started and self.running:
            time.sleep(0.1)

        success = True

        if performHandshake:
            collector = Collector(timeout=0.25, topic=UartTopics.hello)
            self.writeHello()
            reply = collector.receive_sync()

            success = False
            if isinstance(reply, UartCrownstoneHelloPacket):
                success = True
                _LOGGER.debug("Handshake successful")
            else:
                if self.port == port:
                    _LOGGER.warning(
                        "Handshake failed: no reply from the crownstone.")
                else:
                    _LOGGER.debug(
                        "Handshake failed: no reply from the crownstone.")

        if not success:
            _LOGGER.debug("Reinitialization required")
            self._attemptingIndex += 1
            self._uartBridge.stop()
            while self._uartBridge.started and self.running:
                time.sleep(0.1)
        else:
            _LOGGER.info("Connection established to {}".format(port))
            self.port = port
            self.ready = True
            UartEventBus.emit(SystemTopics.connectionEstablished)
Esempio n. 20
0
    def initialize_usb_sync(self,
                            port=None,
                            baudrate=230400,
                            writeChunkMaxSize=0):
        """
        Initialize a Crownstone serial device. 
            
        :param port: serial port of the USB. e.g. '/dev/ttyUSB0' or 'COM3'.
        :param baudrate: baudrate that should be used for this connection. default is 230400.
        :param writeChunkMaxSize: writing in chunks solves issues writing to certain JLink chips. A max chunkSize of 64 was found to work well for our case.
            For normal usage with Crownstones this is not required. a writeChunkMaxSize of 0 will not send the payload in chunks.
        """
        self.uartManager.config(port, baudrate, writeChunkMaxSize)

        result = [False]

        def handleMessage(result, data):
            result[0] = True

        event = UartEventBus.subscribe(
            SystemTopics.connectionEstablished,
            lambda data: handleMessage(result, data))
        self.uartManager.start()

        try:
            while not result[0] and self.running:
                try:
                    exc = self.manager_exception_queue.get(block=False)
                    self.uartManager.join()
                    self.stop()
                    raise exc[0](exc[1])
                except queue.Empty:
                    pass

                time.sleep(0.1)

        except KeyboardInterrupt:
            print("\nClosing Crownstone Uart.... Thanks for your time!")
            self.stop()

        UartEventBus.unsubscribe(event)
    def __init__(self, port, baudrate, writeChunkMaxSize=0):
        self.baudrate = baudrate
        self.port = port
        self.writeChunkMaxSize = writeChunkMaxSize

        self.serialController = None
        self.started = False

        self.running = True
        self.parser = UartParser()
        self.eventId = UartEventBus.subscribe(SystemTopics.uartWriteData, self.write_to_uart)
        threading.Thread.__init__(self)
    def start_reading(self):
        readBuffer = UartReadBuffer()
        self.started = True
        _LOGGER.debug(F"Read starting on serial port {self.port} {self.running}")
        try:
            while self.running:
                bytesFromSerial = self.serialController.read() # reads single byte (blocks until it is received)
                if bytesFromSerial:
                    # read all extra bytes in read buffer
                    if self.serialController.in_waiting > 0:
                        additionalBytes = self.serialController.read(self.serialController.in_waiting)
                        bytesFromSerial = bytesFromSerial + additionalBytes

                    UartEventBus.emit(SystemTopics.uartRawData, bytesFromSerial)
                    readBuffer.addByteArray(bytesFromSerial)
        except OSError or serial.SerialException:
            _LOGGER.info("Connection to USB Failed. Retrying...")
        except KeyboardInterrupt:
            self.running = False
            _LOGGER.debug("Closing serial connection.")
        except Exception as error:
            self.running = False
            _LOGGER.error(f"Error in handling UART data: {error}")
            traceback.print_exc()

        # close the serial controller
        self.serialController.close()
        self.serialController = None
        # remove the event listener pointing to the old connection
        UartEventBus.unsubscribe(self.eventId)
        self.started = False
        UartEventBus.emit(SystemTopics.connectionClosed, True)
    async def setPowerZero(self, mW: int):
        controlPacket = ControlStateSetPacket(
            StateType.POWER_ZERO).loadInt32(mW).serialize()
        uartMessage = UartMessagePacket(UartTxType.CONTROL,
                                        controlPacket).serialize()
        uartPacket = UartWrapperPacket(UartMessageType.UART_MESSAGE,
                                       uartMessage).serialize()

        resultCollector = Collector(timeout=1, topic=SystemTopics.resultPacket)
        # send the message to the Crownstone
        UartEventBus.emit(SystemTopics.uartWriteData, uartPacket)

        # wait for the collectors to fill
        commandResultData = await resultCollector.receive()

        if commandResultData is not None:
            if commandResultData.resultCode is ResultValue.BUSY:
                await asyncio.sleep(0.2)
                return await self.setPowerZero(mW)
            elif commandResultData.resultCode is not ResultValue.SUCCESS:
                raise CrownstoneException(commandResultData.resultCode,
                                          "Command has failed.")
Esempio n. 24
0
    async def _write(self, controlPacket: [int], successCodes = [ResultValue.SUCCESS, ResultValue.SUCCESS_NO_CHANGE, ResultValue.WAIT_FOR_SUCCESS]) -> [int] or None:
        """
        Returns the result payload.
        TODO: return result packet.
        TODO: use a ControlPacket as param, instead of int array.
        """
        _LOGGER.debug(f"Write control packet {controlPacket}")
        uartMessage = UartMessagePacket(UartTxType.CONTROL, controlPacket).serialize()
        uartPacket = UartWrapperPacket(UartMessageType.UART_MESSAGE, uartMessage).serialize()

        resultCollector = Collector(timeout=1, topic=SystemTopics.resultPacket)
        # send the message to the Crownstone
        UartEventBus.emit(SystemTopics.uartWriteData, uartPacket)

        # wait for the collectors to fill
        commandResultData = await resultCollector.receive()

        if commandResultData is not None:
            if commandResultData.resultCode not in successCodes:
                raise CrownstoneException(commandResultData.resultCode, f"Command has failed: result code is {commandResultData.resultCode}")
            return commandResultData.payload
        return None
Esempio n. 25
0
    async def _command_via_mesh_broadcast_acked(
            self, crownstone_uid_array: List[int],
            packet: bytearray) -> MeshResult:
        # this is only for the set_iBeacon_config_id
        # broadcast to all, but retry until ID's in list have acked or timeout
        # value: 3
        corePacket = MeshBroadcastAckedPacket(crownstone_uid_array,
                                              packet).getPacket()
        controlPacket = ControlPacket(
            ControlType.MESH_COMMAND).loadByteArray(corePacket).getPacket()
        uartMessage = UartMessagePacket(UartTxType.CONTROL,
                                        controlPacket).getPacket()
        uartPacket = UartWrapperPacket(UartMessageType.UART_MESSAGE,
                                       uartMessage).getPacket()

        resultCollector = Collector(timeout=2, topic=SystemTopics.resultPacket)
        individualCollector = BatchCollector(
            timeout=15, topic=SystemTopics.meshResultPacket)
        finalCollector = Collector(timeout=15,
                                   topic=SystemTopics.meshResultFinalPacket)

        # send the message to the Crownstone
        UartEventBus.emit(SystemTopics.uartWriteData, uartPacket)

        # wait for the collectors to fill
        commandResultData = await resultCollector.receive()
        if commandResultData is not None:
            if commandResultData.resultCode is ResultValue.BUSY:
                await asyncio.sleep(0.2)
                return await self._command_via_mesh_broadcast_acked(
                    crownstone_uid_array, packet)
            elif commandResultData.resultCode is not ResultValue.SUCCESS:
                raise CrownstoneException(commandResultData.resultCode,
                                          "Command has failed.")

        return await self._handleCollectors(crownstone_uid_array,
                                            individualCollector,
                                            finalCollector)
Esempio n. 26
0
    def __init__(self):
        self.port = None  # Port configured by user.
        self.baudRate = 230400
        self.writeChunkMaxSize = 0
        self.running = True
        self.loop = None
        self._availablePorts = list(list_ports.comports())
        self._attemptingIndex = 0
        self._uartBridge = None
        self.ready = False
        self.eventId = UartEventBus.subscribe(SystemTopics.connectionClosed,
                                              self.resetEvent)

        threading.Thread.__init__(self)
Esempio n. 27
0
    async def _set_state_via_mesh_acked(self, crownstone_id: int,
                                        packet: bytearray) -> MeshResult:
        # 1:1 message to N crownstones with acks (only N = 1 supported for now)
        # flag value: 2
        corePacket = MeshSetStatePacket(crownstone_id, packet).getPacket()
        controlPacket = ControlPacket(
            ControlType.MESH_COMMAND).loadByteArray(corePacket).getPacket()
        uartMessage = UartMessagePacket(UartTxType.CONTROL,
                                        controlPacket).getPacket()
        uartPacket = UartWrapperPacket(UartMessageType.UART_MESSAGE,
                                       uartMessage).getPacket()

        resultCollector = Collector(timeout=2, topic=SystemTopics.resultPacket)
        individualCollector = BatchCollector(
            timeout=15, topic=SystemTopics.meshResultPacket)
        finalCollector = Collector(timeout=15,
                                   topic=SystemTopics.meshResultFinalPacket)

        # send the message to the Crownstone
        UartEventBus.emit(SystemTopics.uartWriteData, uartPacket)

        # wait for the collectors to fill
        commandResultData = await resultCollector.receive()

        if commandResultData is not None:
            if commandResultData.resultCode is ResultValue.BUSY:
                await asyncio.sleep(0.2)
                return await self._set_state_via_mesh_acked(
                    crownstone_id, packet)
            elif commandResultData.resultCode is not ResultValue.SUCCESS:
                raise CrownstoneException(commandResultData.resultCode,
                                          "Command has failed.")

        return await self._handleCollectors([crownstone_id],
                                            individualCollector,
                                            finalCollector)
Esempio n. 28
0
    def process(self):
        """
        Process a buffer.

        Check CRC, and emit a uart packet.

        Buffer starts after size header, and includes wrapper header and tail (CRC).
        """

        # Check size
        bufferSize = len(self.buffer)
        wrapperSize = WRAPPER_HEADER_SIZE + CRC_SIZE
        if bufferSize < wrapperSize:
            _LOGGER.warning("Buffer too small")
            UartEventBus.emit(DevTopics.uartNoise, "buffer too small")
            return

        # Get the buffer between size field and CRC:
        baseBuffer = self.buffer[0:bufferSize - CRC_SIZE]

        # Check CRC
        calculatedCrc = crc16ccitt(baseBuffer)
        sourceCrc = Conversion.uint8_array_to_uint16(self.buffer[bufferSize -
                                                                 CRC_SIZE:])

        if calculatedCrc != sourceCrc:
            _LOGGER.warning("Failed CRC")
            _LOGGER.debug(
                f"Failed CRC: sourceCrc={sourceCrc} calculatedCrc={calculatedCrc} bufSize={len(self.buffer)} buffer={self.buffer}"
            )
            UartEventBus.emit(DevTopics.uartNoise, "crc mismatch")
            return

        wrapperPacket = UartWrapperPacket()
        if wrapperPacket.parse(baseBuffer):
            UartEventBus.emit(SystemTopics.uartNewPackage, wrapperPacket)
Esempio n. 29
0
 def __init__(self):
     self.stones = {}
     UartEventBus.subscribe(SystemTopics.stateUpdate,
                            self.handleStateUpdate)
Esempio n. 30
0
 def emitNewData(self, advPayload):
     UartEventBus.emit(UartTopics.newDataAvailable, advPayload)