/* Initialise the EddystoneService using parameters from persistent storage */ EddystoneService::EddystoneService(BLE &bleIn, EddystoneParams_t ¶msIn, const PowerLevels_t &radioPowerLevelsIn, uint32_t advConfigIntervalIn) : ble(bleIn), operationMode(EDDYSTONE_MODE_NONE), urlFrame(paramsIn.urlData, paramsIn.urlDataLength), uidFrame(paramsIn.uidNamespaceID, paramsIn.uidInstanceID), tlmFrame(paramsIn.tlmVersion), resetFlag(false), rawUrlFrame(NULL), rawUidFrame(NULL), rawTlmFrame(NULL), tlmBatteryVoltageCallback(NULL), tlmBeaconTemperatureCallback(NULL), uidFrameCallbackHandle(NULL), urlFrameCallbackHandle(NULL), tlmFrameCallbackHandle(NULL), radioManagerCallbackHandle(NULL), deviceName(DEFAULT_DEVICE_NAME) { lockState = paramsIn.lockState; flags = paramsIn.flags; txPowerMode = paramsIn.txPowerMode; urlFramePeriod = correctAdvertisementPeriod(paramsIn.urlFramePeriod); uidFramePeriod = correctAdvertisementPeriod(paramsIn.uidFramePeriod); tlmFramePeriod = correctAdvertisementPeriod(paramsIn.tlmFramePeriod); memcpy(lock, paramsIn.lock, sizeof(Lock_t)); memcpy(unlock, paramsIn.unlock, sizeof(Lock_t)); eddystoneConstructorHelper(paramsIn.advPowerLevels, radioPowerLevelsIn, advConfigIntervalIn); }
void EddystoneService::setTLMFrameAdvertisingInterval(uint16_t tlmFrameIntervalIn) { if (tlmFrameIntervalIn == tlmFramePeriod) { /* Do nothing */ return; } /* Make sure the input period is within bounds */ tlmFramePeriod = correctAdvertisementPeriod(tlmFrameIntervalIn); if (operationMode == EDDYSTONE_MODE_BEACON) { if (tlmFrameCallbackHandle) { /* The advertisement interval changes, update minar periodic callback */ minar::Scheduler::cancelCallback(tlmFrameCallbackHandle); } else { /* This frame was just enabled */ if (!rawTlmFrame && tlmFramePeriod) { /* Allocate memory for this frame and construct it */ rawTlmFrame = new uint8_t[tlmFrame.getRawFrameSize()]; /* Do not construct the TLM frame because this changes every 0.1 seconds */ } } if (tlmFramePeriod) { /* Currently the only way to change the period of a callback in minar * is to cancell it and reschedule */ tlmFrameCallbackHandle = minar::Scheduler::postCallback( mbed::util::FunctionPointer1<void, FrameType>(this, &EddystoneService::enqueueFrame).bind(EDDYSTONE_FRAME_TLM) ).period(minar::milliseconds(tlmFramePeriod)).getHandle(); } else { tlmFrameCallbackHandle = NULL; } } }
void EddystoneService::setNormalFrameAdvertisingInterval(uint16_t normalFrameIntervalIn) { if (normalFrameIntervalIn == normalFramePeriod) { /* Do nothing */ return; } /* Make sure the input period is within bounds */ normalFramePeriod = correctAdvertisementPeriod(normalFrameIntervalIn); if (operationMode == EDDYSTONE_MODE_BEACON) { if (normalFrameCallbackHandle) { /* The advertisement interval changes, update minar periodic callback */ minar::Scheduler::cancelCallback(normalFrameCallbackHandle); } else { /* This frame was just enabled */ // if (!rawUidFrame && normalFramePeriod) { // /* Allocate memory for this frame and construct it */ // rawUidFrame = new uint8_t[uidFrame.getRawFrameSize()]; // uidFrame.constructUIDFrame(rawUidFrame, advPowerLevels[txPowerMode]); // } } if (normalFramePeriod) { /* Currently the only way to change the period of a callback in minar * is to cancell it and reschedule */ normalFrameCallbackHandle = minar::Scheduler::postCallback( mbed::util::FunctionPointer1<void, FrameType>(this, &EddystoneService::enqueueFrame).bind(NORMAL_FRAME) ).period(minar::milliseconds(normalFramePeriod)).getHandle(); } else { normalFrameCallbackHandle = NULL; } } }
/* * This callback is invoked when a GATT client attempts to modify any of the * characteristics of this service. Attempts to do so are also applied to * the internal state of this service object. */ void EddystoneService::onDataWrittenCallback(const GattWriteCallbackParams *writeParams) { uint16_t handle = writeParams->handle; if (handle == lockChar->getValueHandle()) { memcpy(lock, writeParams->data, sizeof(Lock_t)); /* Set the state to be locked by the lock code (note: zeros are a valid lock) */ lockState = true; ble.gattServer().write(lockChar->getValueHandle(), lock, sizeof(PowerLevels_t)); ble.gattServer().write(lockStateChar->getValueHandle(), reinterpret_cast<uint8_t *>(&lockState), sizeof(bool)); } else if (handle == unlockChar->getValueHandle()) { /* Validated earlier */ lockState = false; ble.gattServer().write(unlockChar->getValueHandle(), unlock, sizeof(PowerLevels_t)); ble.gattServer().write(lockStateChar->getValueHandle(), reinterpret_cast<uint8_t *>(&lockState), sizeof(bool)); } else if (handle == urlDataChar->getValueHandle()) { urlFrame.setEncodedURLData(writeParams->data, writeParams->len); ble.gattServer().write(urlDataChar->getValueHandle(), urlFrame.getEncodedURLData(), urlFrame.getEncodedURLDataLength()); } else if (handle == flagsChar->getValueHandle()) { flags = *(writeParams->data); ble.gattServer().write(flagsChar->getValueHandle(), &flags, sizeof(uint8_t)); } else if (handle == advPowerLevelsChar->getValueHandle()) { memcpy(advPowerLevels, writeParams->data, sizeof(PowerLevels_t)); ble.gattServer().write(advPowerLevelsChar->getValueHandle(), reinterpret_cast<uint8_t *>(advPowerLevels), sizeof(PowerLevels_t)); } else if (handle == txPowerModeChar->getValueHandle()) { txPowerMode = *(writeParams->data); ble.gattServer().write(txPowerModeChar->getValueHandle(), &txPowerMode, sizeof(uint8_t)); } else if (handle == beaconPeriodChar->getValueHandle()) { uint16_t tmpBeaconPeriod = correctAdvertisementPeriod(*((uint16_t *)(writeParams->data))); if (tmpBeaconPeriod != urlFramePeriod) { urlFramePeriod = tmpBeaconPeriod; ble.gattServer().write(beaconPeriodChar->getValueHandle(), reinterpret_cast<uint8_t *>(&urlFramePeriod), sizeof(uint16_t)); } } else if (handle == resetChar->getValueHandle() && (*((uint8_t *)writeParams->data) != 0)) { /* Reset characteristics to default values */ flags = 0; txPowerMode = TX_POWER_MODE_LOW; urlFramePeriod = DEFAULT_URL_FRAME_PERIOD_MSEC; urlFrame.setURLData(DEFAULT_URL); memset(lock, 0, sizeof(Lock_t)); ble.gattServer().write(urlDataChar->getValueHandle(), urlFrame.getEncodedURLData(), urlFrame.getEncodedURLDataLength()); ble.gattServer().write(flagsChar->getValueHandle(), &flags, sizeof(uint8_t)); ble.gattServer().write(txPowerModeChar->getValueHandle(), &txPowerMode, sizeof(uint8_t)); ble.gattServer().write(beaconPeriodChar->getValueHandle(), reinterpret_cast<uint8_t *>(&urlFramePeriod), sizeof(uint16_t)); ble.gattServer().write(lockChar->getValueHandle(), lock, sizeof(PowerLevels_t)); } }
void EddystoneService::setURLFrameAdvertisingInterval(uint16_t urlFrameIntervalIn) { if (urlFrameIntervalIn == urlFramePeriod) { /* Do nothing */ return; } /* Make sure the input period is within bounds */ urlFramePeriod = correctAdvertisementPeriod(urlFrameIntervalIn); if (operationMode == EDDYSTONE_MODE_BEACON) { if (urlFrameCallbackHandle) { /* The advertisement interval changes, update minar periodic callback */ minar::Scheduler::cancelCallback(urlFrameCallbackHandle); } else { /* This frame was just enabled */ if (!rawUidFrame && urlFramePeriod) { /* Allocate memory for this frame and construct it */ rawUrlFrame = new uint8_t[urlFrame.getRawFrameSize()]; urlFrame.constructURLFrame(rawUrlFrame, advPowerLevels[txPowerMode]); } } if (urlFramePeriod) { /* Currently the only way to change the period of a callback in minar * is to cancell it and reschedule */ urlFrameCallbackHandle = minar::Scheduler::postCallback( mbed::util::FunctionPointer1<void, FrameType>(this, &EddystoneService::enqueueFrame).bind(EDDYSTONE_FRAME_URL) ).period(minar::milliseconds(urlFramePeriod)).getHandle(); } else { urlFrameCallbackHandle = NULL; } } else if (operationMode == EDDYSTONE_MODE_CONFIG) { ble.gattServer().write(beaconPeriodChar->getValueHandle(), reinterpret_cast<uint8_t *>(&urlFramePeriod), sizeof(uint16_t)); } }