async def resetErrors(self, bitmask: int = 0xFFFFFFFF): """ Resets errors. @param bitmask: A 32b bitmask of the errors to reset. """ await self._writeControlAndGetResult( ControlPacketsGenerator.getResetErrorPacket(bitmask))
async def periodically_activate_ibeacon_index( self, crownstone_uid_array: List[int], index: int, interval_seconds: int, offset_seconds: int = 0) -> MeshResult: """ You need to have 2 stored ibeacon payloads (state index 0 and 1) in order for this to work. This can be done by the set_ibeacon methods available in this class. Once the interval starts, it will set this ibeacon ID to be active. In order to have 2 ibeacon payloads interleaving, you have to call this method twice. To interleave every minute First, periodically_activate_ibeacon_index, index 0, interval = 120 (2 minutes), offset = 0 Secondly, periodically_activate_ibeacon_index, index 1, interval = 120 (2 minutes), offset = 60 This will change the active ibeacon payload every minute: T = 0.............60.............120.............180.............240 activeId = 0.............1...............0...............1...............0 period_0 = |------------120s-------------|--------------120s-------------| :param crownstone_uid_array: :param index: :param interval_seconds: :param offset_seconds: :return: """ ibeaconConfigPacket = ControlPacketsGenerator.getIBeaconConfigIdPacket( index, offset_seconds, interval_seconds) return await self._command_via_mesh_broadcast_acked( crownstone_uid_array, ibeaconConfigPacket)
async def removeFilter(self, filterId): """ Remove an asset filter from the Crownstones. Once all changes are made, don't forget to commit them. :param filterId: The filter ID to be removed. """ _LOGGER.info(f"removeFilter id={filterId}") return await self._write(ControlPacketsGenerator.getRemoveFilterPacket(filterId))
async def set_time(self, timestamp=None): if timestamp is None: timestamp = math.ceil(time.time()) localizedTimeStamp = getCorrectedLocalTimestamp(timestamp) time_packet = ControlPacketsGenerator.getSetTimePacket( localizedTimeStamp) await self._command_via_mesh_broadcast(time_packet)
async def stop_ibeacon_interval_and_set_index( self, crownstone_uid_array: List[int], index) -> MeshResult: """ This method stops the interleaving for the specified ibeacon payload at that index. :param crownstone_uid_array: :param index: :return: """ indexToEndWith = index indexToStartWith = 0 if index == 0: indexToStartWith = 1 ibeaconConfigPacketStart = ControlPacketsGenerator.getIBeaconConfigIdPacket( indexToStartWith, 0, 0) ibeaconConfigPacketFinish = ControlPacketsGenerator.getIBeaconConfigIdPacket( indexToEndWith, 0, 0) meshResult = MeshResult(crownstone_uid_array) initialResult = await self._command_via_mesh_broadcast_acked( crownstone_uid_array, ibeaconConfigPacketStart) meshResult.merge(initialResult) successfulIds = meshResult.get_successful_ids() if len(successfulIds) == 0: return meshResult secondResult = await self._command_via_mesh_broadcast_acked( successfulIds, ibeaconConfigPacketFinish) # if we succeeded in the initial phase, we should be able to finish the second case. failed_second_part = meshResult.compare_get_failed(secondResult) iterations = 0 while len(failed_second_part) > 0 and iterations < 5: secondResult = await self._command_via_mesh_broadcast_acked( failed_second_part, ibeaconConfigPacketFinish) failed_second_part = meshResult.compare_get_failed(secondResult) iterations += 1 meshResult.merge(secondResult) meshResult.conclude() return meshResult
async def commitFilterChanges(self, masterVersion: int, filters: List[AssetFilter], filterSummaries: List[FilterSummaryPacket] = None): """ Commit the changes made by upload and/or remove. :param masterVersion: The new master version, should be higher than previous master version. :param filters: A list of asset filters with filter ID, that are uploaded to the Crowstone. :param filterSummaries : A list of filter summaries that are already on the Crownstone. """ _LOGGER.info(f"commitFilterChanges masterVersion={masterVersion}") masterCrc = AssetFilterMasterCrc.get_master_crc_from_filters(filters, filterSummaries) return await self._write(ControlPacketsGenerator.getCommitFilterChangesPacket(masterVersion, masterCrc))
async def uploadFilter(self, filter: AssetFilter): """ Upload an asset filter to the Crownstones. Once all changes are made, don't forget to commit them. :param filter: The asset filter to be uploaded. """ _LOGGER.info(f"uploadFilter {filter}") chunker = FilterChunker(filter, 128) result = None for i in range(0, chunker.getAmountOfChunks()): chunk = chunker.getChunk() result = await self._write(ControlPacketsGenerator.getUploadFilterPacket(chunk)) return result
async def _writeFastSetupV2(self, sphereId, crownstoneId, meshDeviceKey, ibeaconUUID, ibeaconMajor, ibeaconMinor): packet = ControlPacketsGenerator.getSetupPacket( crownstoneId, sphereId, self.core.settings.adminKey, self.core.settings.memberKey, self.core.settings.basicKey, self.core.settings.serviceDataKey, self.core.settings.localizationKey, meshDeviceKey, self.core.settings.meshApplicationKey, self.core.settings.meshNetworkKey, ibeaconUUID, ibeaconMajor, ibeaconMinor) _LOGGER.info("Writing setup data to Crownstone...") await self.core.ble.writeToCharacteristic( CSServices.SetupService, SetupCharacteristics.SetupControl, packet)
async def getFilterSummaries(self) -> FilterSummariesPacket: """ Get a summary of the filters that are on the Crownstones. This can be used to determine: - Which filters should be changed. - What the next master version should be. - How much space there is left for new filters. - The new master CRC. :return: The filter summaries packet. """ _LOGGER.info(f"getFilterSummaries") result = await self._write(ControlPacketsGenerator.getGetFilterSummariesPacket()) if result is None: raise CrownstoneException(CrownstoneError.DATA_MISSING, "No summaries received") summaries = FilterSummariesPacket(result) return summaries
async def disconnect(self): """ Force the Crownstone to disconnect from you. """ try: #print("Send disconnect command") await self._writeControlPacket( ControlPacketsGenerator.getDisconnectPacket()) except Exception as err: # TODO: catch this error if it is something like already disconnected #print("Unknown error") raise err try: # Disconnect from this side as well. #print("Disconnect from this side as well") self.core.ble.disconnect() except Exception as err: #print("Unknown error") raise err
def setup() -> bool: logging.log(logging.INFO, "Perform setup") try: controlPacket = ControlPacketsGenerator.getSetupPacket( crownstoneId=crownstoneId, sphereId=sphereId, adminKey=Conversion.ascii_or_hex_string_to_16_byte_array(adminKey), memberKey=Conversion.ascii_or_hex_string_to_16_byte_array( memberKey), basicKey=Conversion.ascii_or_hex_string_to_16_byte_array(basicKey), serviceDataKey=Conversion.ascii_or_hex_string_to_16_byte_array( serviceDataKey), localizationKey=Conversion.ascii_or_hex_string_to_16_byte_array( localizationKey), meshDeviceKey=Conversion.ascii_or_hex_string_to_16_byte_array( meshDeviceKey), meshAppKey=Conversion.ascii_or_hex_string_to_16_byte_array( meshAppKey), meshNetworkKey=Conversion.ascii_or_hex_string_to_16_byte_array( meshNetworkKey), ibeaconUUID=ibeaconUUID, ibeaconMajor=ibeaconMajor, ibeaconMinor=ibeaconMinor) uartMessage = UartMessagePacket(UartTxType.CONTROL, controlPacket).getPacket() uartPacket = UartWrapperPacket(UartMessageType.UART_MESSAGE, uartMessage).getPacket() result = UartWriter(uartPacket).write_with_result_sync( [ResultValue.SUCCESS, ResultValue.WAIT_FOR_SUCCESS]) if result.resultCode is ResultValue.SUCCESS: return True if result.resultCode is ResultValue.WAIT_FOR_SUCCESS: # Actually we should wait for the next result code.. time.sleep(3.0) return True logging.log(logging.WARN, f"Setup failed, result={result}") return False except CrownstoneException as e: logging.log(logging.WARN, f"Failed to setup: {e}") return False
def factoryReset() -> bool: logging.log(logging.INFO, "Factory reset") try: controlPacket = ControlPacketsGenerator.getCommandFactoryResetPacket() uartMessage = UartMessagePacket(UartTxType.CONTROL, controlPacket).getPacket() uartPacket = UartWrapperPacket(UartMessageType.UART_MESSAGE, uartMessage).getPacket() result = UartWriter(uartPacket).write_with_result_sync( [ResultValue.SUCCESS, ResultValue.WAIT_FOR_SUCCESS]) if result.resultCode is ResultValue.SUCCESS: # This always returns SUCCESS, while we should actually wait. time.sleep(10.0) return True if result.resultCode is ResultValue.WAIT_FOR_SUCCESS: # Actually we should wait for the next result code.. time.sleep(10.0) return True logging.log(logging.WARN, f"Factory reset failed, result={result}") return False except CrownstoneException as e: logging.log(logging.WARN, f"Failed to factory reset: {e}") return False
async def allowDimming(self, allow: bool): """ :param allow: True to allow dimming """ await self._writeControlPacket( ControlPacketsGenerator.getAllowDimmingPacket(allow))
async def commandFactoryReset(self): """ If you have the keys, you can use this to put the crownstone back into factory default mode """ await self._writeControlPacket( ControlPacketsGenerator.getCommandFactoryResetPacket())
async def setDimmer(self, intensity: int): """ :param intensity: percentage [0..100] """ await self._writeControlPacket( ControlPacketsGenerator.getDimmerSwitchPacket(intensity))
async def setRelay(self, turnOn: bool): """ :param turnOn: True to turn relay on. """ await self._writeControlPacket( ControlPacketsGenerator.getRelaySwitchPacket(turnOn))
async def setSwitch(self, switchVal: int): """ :param switchVal: 0% .. 100% or special value (SwitchValSpecial). """ await self._writeControlPacket( ControlPacketsGenerator.getSwitchCommandPacket(switchVal))
async def _recoveryByFactoryReset(self): packet = ControlPacketsGenerator.getFactoryResetPacket() return self.core.ble.writeToCharacteristicWithoutEncryption( CSServices.CrownstoneService, CrownstoneCharacteristics.FactoryReset, packet)
async def _getPowerSamples(self, samplesType, index): """ Get power samples of given type at given index, but don't check result code. """ controlPacket = ControlPacketsGenerator.getPowerSamplesRequestPacket(samplesType, index) return await self._writeControlAndGetResult(controlPacket)
async def lockSwitch(self, lock): """ :param lock: bool """ await self._writeControlPacket( ControlPacketsGenerator.getLockSwitchPacket(lock))
async def putInDfuMode(self): """ Puts the crownstone in DFU mode. """ await self._writeControlAndGetResult( ControlPacketsGenerator.getPutInDFUPacket())
async def reset(self): await self._writeControlPacket( ControlPacketsGenerator.getResetPacket())
async def reset_errors(self): control_packet = ControlPacketsGenerator.getResetErrorPacket( 0xFFFFFFFF) await self._command_via_mesh_broadcast(control_packet)