async def write(self) -> True:
        """
        write will take the data packet you have provided to the constructor and send it over UART.
        You can await the success of the write. 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

            await asyncio.sleep(self.interval)
            counter += self.interval


        self._wrapUpFailedWrite()
    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. 3
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. 4
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)
    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. 6
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. 7
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. 8
0
 def emitNewData(self, advPayload):
     UartEventBus.emit(UartTopics.newDataAvailable, advPayload)
    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 Exception as e:
                UartEventBus.emit(SystemTopics.uartWriteError, {"message": "Unknown Exception 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. 10
0
 def _send(self, opCode: UartTxType, payload: list):
     # send over uart
     uartMessage = UartMessagePacket(opCode, payload).getPacket()
     uartPacket = UartWrapperPacket(UartMessageType.UART_MESSAGE,
                                    uartMessage).getPacket()
     UartEventBus.emit(SystemTopics.uartWriteData, uartPacket)
 def writeHello(self):
     helloPacket = UartCommandHelloPacket().serialize()
     uartMessage = UartMessagePacket(UartTxType.HELLO, helloPacket).serialize()
     uartPacket = UartWrapperPacket(UartMessageType.UART_MESSAGE, uartMessage).serialize()
     UartEventBus.emit(SystemTopics.uartWriteData, uartPacket)
 def echo(self, string):
     controlPacket = ControlPacket(ControlType.UART_MESSAGE).loadString(string).serialize()
     uartMessage   = UartMessagePacket(UartTxType.CONTROL, controlPacket).serialize()
     uartPacket    = UartWrapperPacket(UartMessageType.UART_MESSAGE, uartMessage).serialize()
     UartEventBus.emit(SystemTopics.uartWriteData, uartPacket)
    def _handleUartMessage(self, messagePacket: UartMessagePacket):
        """
        Callback for SystemTopics.uartNewMessage. This transforms a select number of message types
        into further specialized messages and posts those on UartEventBus.
        :param messagePacket:
        :return:
        """
        opCode = messagePacket.opCode
        parsedData = None
        # print("UART - opCode:", opCode, "payload:", dataPacket.payload)

        if opCode == UartRxType.HELLO:
            helloPacket = UartCrownstoneHelloPacket(messagePacket.payload)
            UartEventBus.emit(UartTopics.hello, helloPacket)
            pass

        elif opCode == UartRxType.SESSION_NONCE:
            _LOGGER.debug(f"Received SESSION_NONCE")
            pass

        elif opCode == UartRxType.HEARTBEAT:
            _LOGGER.debug(f"Received HEARTBEAT")
            pass

        elif opCode == UartRxType.STATUS:
            _LOGGER.debug(f"Received STATUS")
            pass

        elif opCode == UartRxType.RESULT_PACKET:
            packet = ResultPacket(messagePacket.payload)
            UartEventBus.emit(SystemTopics.resultPacket, packet)

        #################
        # Error replies #
        #################

        elif opCode == UartRxType.ERR_REPLY_PARSING_FAILED:
            _LOGGER.debug(f"Received ERR_REPLY_PARSING_FAILED")
            pass

        elif opCode == UartRxType.ERR_REPLY_STATUS:
            _LOGGER.debug(f"Received ERR_REPLY_STATUS")
            pass

        elif opCode == UartRxType.ERR_REPLY_SESSION_NONCE_MISSING:
            _LOGGER.debug(f"Received ERR_REPLY_SESSION_NONCE_MISSING")
            pass

        elif opCode == UartRxType.ERR_REPLY_DECRYPTION_FAILED:
            _LOGGER.debug(f"Received ERR_REPLY_DECRYPTION_FAILED")
            pass

        elif 9900 < opCode < 10000:
            _LOGGER.debug(f"Received ERR_REPLY {opCode}")
            pass

        ################
        #### Events ####
        ################

        elif opCode == UartRxType.UART_MESSAGE:
            stringResult = ""
            for byte in messagePacket.payload:
                stringResult += chr(byte)
            # logStr = "LOG: %15.3f - %s" % (time.time(), stringResult)
            UartEventBus.emit(UartTopics.uartMessage, {
                "string": stringResult,
                "data": messagePacket.payload
            })

        elif opCode == UartRxType.SESSION_NONCE_MISSING:
            _LOGGER.debug(f"Received SESSION_NONCE_MISSING")
            pass

        elif opCode == UartRxType.OWN_SERVICE_DATA:
            # service data type + device type + data type + service data (15b)
            serviceData = ServiceData(messagePacket.payload)
            serviceData.parse()
            UartEventBus.emit(DevTopics.newServiceData, serviceData.payload)

        elif opCode == UartRxType.PRESENCE_CHANGE:
            pass

        elif opCode == UartRxType.FACTORY_RESET:
            pass

        elif opCode == UartRxType.BOOTED:
            _LOGGER.debug(f"Received BOOTED")
            pass

        elif opCode == UartRxType.HUB_DATA:
            pass

        elif opCode == UartRxType.MESH_SERVICE_DATA:
            # data type + service data (15b)
            result = parseOpcode7(messagePacket.payload)
            if hasattr(result, "crownstoneId"):
                UartEventBus.emit(SystemTopics.stateUpdate,
                                  (result.crownstoneId, result))

        elif opCode == UartRxType.EXTERNAL_STATE_PART_0:
            pass

        elif opCode == UartRxType.EXTERNAL_STATE_PART_1:
            pass

        elif opCode == UartRxType.MESH_RESULT:
            if len(messagePacket.payload) > 1:
                crownstoneId = messagePacket.payload[0]
                packet = ResultPacket(messagePacket.payload[1:])
                UartEventBus.emit(SystemTopics.meshResultPacket,
                                  [crownstoneId, packet])

        elif opCode == UartRxType.MESH_ACK_ALL_RESULT:
            packet = ResultPacket(messagePacket.payload)
            UartEventBus.emit(SystemTopics.meshResultFinalPacket, packet)

        elif opCode == UartRxType.RSSI_PING_MESSAGE:
            # for now, you can subscribe to SystemTopics.uartNewMessage
            pass

        elif opCode == UartRxType.LOG:
            _LOGGER.debug(f"Received binary log: {messagePacket.payload}")
            packet = UartLogPacket(messagePacket.payload)
            UartEventBus.emit(UartTopics.log, packet)

        elif opCode == UartRxType.LOG_ARRAY:
            _LOGGER.debug(
                f"Received binary log array: {messagePacket.payload}")
            packet = UartLogArrayPacket(messagePacket.payload)
            UartEventBus.emit(UartTopics.logArray, packet)

        ####################
        # Developer events #
        ####################

        elif opCode == UartRxType.INTERNAL_EVENT:
            pass

        elif opCode == UartRxType.MESH_CMD_TIME:
            pass

        elif opCode == UartRxType.MESH_PROFILE_LOCATION:
            pass

        elif opCode == UartRxType.MESH_SET_BEHAVIOUR_SETTINGS:
            pass

        elif opCode == UartRxType.MESH_TRACKED_DEVICE_REGISTER:
            pass

        elif opCode == UartRxType.MESH_TRACKED_DEVICE_TOKEN:
            pass

        elif opCode == UartRxType.MESH_SYNC_REQUEST:
            pass

        elif opCode == UartRxType.MESH_TRACKED_DEVICE_HEARTBEAT:
            pass

        ######################
        # Debug build events #
        ######################

        elif opCode == UartRxType.ADVERTISING_ENABLED:
            pass

        elif opCode == UartRxType.MESH_ENABLED:
            pass

        elif opCode == UartRxType.CROWNSTONE_ID:
            id = Conversion.int8_to_uint8(messagePacket.payload)
            UartEventBus.emit(DevTopics.ownCrownstoneId, id)

        elif opCode == UartRxType.MAC_ADDRESS:
            addr = Conversion.uint8_array_to_address(messagePacket.payload)
            if addr != "":
                UartEventBus.emit(DevTopics.ownMacAddress, addr)
            else:
                _LOGGER.warning("invalid address:", messagePacket.payload)

        elif opCode == UartRxType.ADC_CONFIG:
            # type is PowerCalculationsPacket
            parsedData = AdcConfigPacket(messagePacket.payload)
            UartEventBus.emit(DevTopics.newAdcConfigPacket,
                              parsedData.getDict())

        elif opCode == UartRxType.ADC_RESTART:
            UartEventBus.emit(DevTopics.adcRestarted, None)

        elif opCode == UartRxType.POWER_LOG_CURRENT:
            # type is CurrentSamples
            parsedData = CurrentSamplesPacket(messagePacket.payload)
            UartEventBus.emit(DevTopics.newCurrentData, parsedData.getDict())

        elif opCode == UartRxType.POWER_LOG_VOLTAGE:
            # type is VoltageSamplesPacket
            parsedData = VoltageSamplesPacket(messagePacket.payload)
            UartEventBus.emit(DevTopics.newVoltageData, parsedData.getDict())

        elif opCode == UartRxType.POWER_LOG_FILTERED_CURRENT:
            # type is CurrentSamples
            parsedData = CurrentSamplesPacket(messagePacket.payload)
            UartEventBus.emit(DevTopics.newFilteredCurrentData,
                              parsedData.getDict())

        elif opCode == UartRxType.POWER_LOG_FILTERED_VOLTAGE:
            # type is VoltageSamplesPacket
            parsedData = VoltageSamplesPacket(messagePacket.payload)
            UartEventBus.emit(DevTopics.newFilteredVoltageData,
                              parsedData.getDict())

        elif opCode == UartRxType.POWER_LOG_POWER:
            # type is PowerCalculationsPacket
            parsedData = PowerCalculationPacket(messagePacket.payload)
            UartEventBus.emit(DevTopics.newCalculatedPowerData,
                              parsedData.getDict())

        elif opCode == UartRxType.ASCII_LOG:
            timestamp = datetime.datetime.now()
            stringResult = ""
            for byte in messagePacket.payload:
                if byte < 128:
                    stringResult += chr(byte)
            logStr = f"ASCII LOG: [{timestamp.strftime(self.timestampFormat)}] {stringResult}"
            # sys.stdout.write(logStr)
            print(logStr.rstrip())

        elif opCode == UartRxType.FIRMWARESTATE:
            # no need to process this, that's in the test suite.
            pass

        else:
            _LOGGER.warning(f"Unknown opCode: {opCode}")

        parsedData = None