This is an example of BLE GATT Client, which receives broadcast data from BLE_Server_BME280 ( a GATT server) , then transfers values up to mbed Device Connector (cloud).
Please refer details about BLEClient_mbedDevConn below. https://github.com/soramame21/BLEClient_mbedDevConn
The location of required BLE GATT server, BLE_Server_BME280, is at here. https://developer.mbed.org/users/edamame22/code/BLE_Server_BME280/
mbed-client/source/m2mreporthandler.cpp
- Committer:
- Ren Boting
- Date:
- 2017-09-05
- Revision:
- 2:b894b3508057
- Parent:
- 0:29983394c6b6
File content as of revision 2:b894b3508057:
/* * Copyright (c) 2015 ARM Limited. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "mbed-client/m2mreportobserver.h" #include "mbed-client/m2mconstants.h" #include "mbed-client/m2mtimer.h" #include "include/m2mreporthandler.h" #include "mbed-trace/mbed_trace.h" #include <string.h> #include <stdlib.h> #define TRACE_GROUP "mClt" M2MReportHandler::M2MReportHandler(M2MReportObserver &observer) : _observer(observer), _attribute_state(0), _notify(false), _pmin_exceeded(false), _pmax_exceeded(false), _pmin_timer(*this), _pmax_timer(*this), _pmax(-1.0f), _pmin(1.0f), _current_value(0.0f), _gt(0.0f), _lt(0.0f), _st(0.0f), _high_step(0.0f), _low_step(0.0f), _last_value(-1.0f) { tr_debug("M2MReportHandler::M2MReportHandler()"); } M2MReportHandler::~M2MReportHandler() { tr_debug("M2MReportHandler::~M2MReportHandler()"); } void M2MReportHandler::set_under_observation(bool observed) { tr_debug("M2MReportHandler::set_under_observation(observed %d)", (int)observed); stop_timers(); if(observed) { handle_timers(); } else { set_default_values(); } } void M2MReportHandler::set_value(float value) { tr_debug("M2MReportHandler::set_value() - current %f, last %f", value, _last_value); _current_value = value; if(_current_value != _last_value) { tr_debug("M2MReportHandler::set_value() - UNDER OBSERVATION"); if (check_threshold_values()) { schedule_report(); } else { tr_debug("M2MReportHandler::set_value - value not in range"); _notify = false; _last_value = _current_value; if ((_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt || (_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt || (_attribute_state & M2MReportHandler::St) == M2MReportHandler::St) { tr_debug("M2MReportHandler::set_value - stop pmin timer"); _pmin_timer.stop_timer(); _pmin_exceeded = true; } } _high_step = _current_value + _st; _low_step = _current_value - _st; } } void M2MReportHandler::set_notification_trigger(uint16_t obj_instance_id) { tr_debug("M2MReportHandler::set_notification_trigger(): %d", obj_instance_id); // Add to array if not there yet m2m::Vector<uint16_t>::const_iterator it; it = _changed_instance_ids.begin(); bool found = false; for ( ; it != _changed_instance_ids.end(); it++) { if ((*it) == obj_instance_id) { found = true; break; } } if (!found) { _changed_instance_ids.push_back(obj_instance_id); } _current_value = 0.0f; _last_value = 1.0f; schedule_report(); } bool M2MReportHandler::parse_notification_attribute(const char *query, M2MBase::BaseType type, M2MResourceInstance::ResourceType resource_type) { tr_debug("M2MReportHandler::parse_notification_attribute(Query %s, Base type %d)", query, (int)type); bool success = false; const char* sep_pos = strchr(query, '&'); const char* rest = query; if( sep_pos != NULL ){ char query_options[5][20]; float pmin = _pmin; float pmax = _pmax; float lt = _lt; float gt = _gt; float st = _st; float high = _high_step; float low = _low_step; uint8_t attr = _attribute_state; memset(query_options, 0, sizeof(query_options[0][0]) * 5 * 20); uint8_t num_options = 0; while( sep_pos != NULL && num_options < 5){ size_t len = (size_t)(sep_pos-rest); if( len > 19 ){ len = 19; } memcpy(query_options[num_options], rest, len); sep_pos++; rest = sep_pos; sep_pos = strchr(rest, '&'); num_options++; } if( num_options < 5 && strlen(rest) > 0){ size_t len = (size_t)strlen(rest); if( len > 19 ){ len = 19; } memcpy(query_options[num_options++], rest, len); } for (int option = 0; option < num_options; option++) { success = set_notification_attribute(query_options[option],type, resource_type); if (!success) { tr_debug("M2MReportHandler::parse_notification_attribute - break"); break; } } if(success) { success = check_attribute_validity(); } else { tr_debug("M2MReportHandler::parse_notification_attribute - not valid query"); _pmin = pmin; _pmax = pmax; _st = st; _lt = lt; _gt = gt; _high_step = high; _low_step = low; _attribute_state = attr; } } else { if(set_notification_attribute(query, type, resource_type)) { success = check_attribute_validity(); } } return success; } void M2MReportHandler::timer_expired(M2MTimerObserver::Type type) { switch(type) { case M2MTimerObserver::PMinTimer: { tr_debug("M2MReportHandler::timer_expired - PMIN"); if (_notify || (_pmin > 0 && (_attribute_state & M2MReportHandler::Pmax) != M2MReportHandler::Pmax)){ report(); } else{ _pmin_exceeded = true; } } break; case M2MTimerObserver::PMaxTimer: { tr_debug("M2MReportHandler::timer_expired - PMAX"); _pmax_exceeded = true; if (_pmin_exceeded || (_attribute_state & M2MReportHandler::Pmin) != M2MReportHandler::Pmin ) { report(); } } break; default: break; } } bool M2MReportHandler::set_notification_attribute(const char* option, M2MBase::BaseType type, M2MResourceInstance::ResourceType resource_type) { tr_debug("M2MReportHandler::set_notification_attribute()"); bool success = false; char attribute[20]; char value[20]; memset(&attribute, 0, 20); memset(&value, 0, 20); const char* pos = strstr(option, EQUAL); if( pos != NULL ){ memcpy(attribute, option, (size_t)(pos-option)); pos++; memcpy(value, pos, strlen(pos)); }else{ memcpy(attribute, option, (size_t)strlen(option) + 1); } if (strlen(value)) { if (strcmp(attribute, PMIN) == 0) { _pmin = atoi(value); success = true; _attribute_state |= M2MReportHandler::Pmin; tr_debug("M2MReportHandler::set_notification_attribute %s to %d", attribute, _pmin); } else if(strcmp(attribute, PMAX) == 0) { _pmax = atoi(value); success = true; _attribute_state |= M2MReportHandler::Pmax; tr_debug("M2MReportHandler::set_notification_attribute %s to %d", attribute, _pmax); } else if(strcmp(attribute, GT) == 0 && (M2MBase::Resource == type)){ _gt = atof(value); success = true; _attribute_state |= M2MReportHandler::Gt; tr_debug("M2MReportHandler::set_notification_attribute %s to %f", attribute, _gt); } else if(strcmp(attribute, LT) == 0 && (M2MBase::Resource == type)){ _lt = atof(value); success = true; _attribute_state |= M2MReportHandler::Lt; tr_debug("M2MReportHandler::set_notification_attribute %s to %f", attribute, _lt); } else if((strcmp(attribute, ST_SIZE) == 0 || (strcmp(attribute, STP) == 0)) && (M2MBase::Resource == type)){ _st = atof(value); success = true; _high_step = _current_value + _st; _low_step = _current_value - _st; _attribute_state |= M2MReportHandler::St; tr_debug("M2MReportHandler::set_notification_attribute %s to %f", attribute, _st); } // Return false if try to set gt,lt or st when the resource type is something else than numerical if ((resource_type != M2MResourceInstance::INTEGER && resource_type != M2MResourceInstance::FLOAT) && ((_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt || (_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt || (_attribute_state & M2MReportHandler::St) == M2MReportHandler::St)) { tr_debug("M2MReportHandler::set_notification_attribute - not numerical resource"); success = false; } } return success; } void M2MReportHandler::schedule_report() { tr_debug("M2MReportHandler::schedule_report()"); _notify = true; if ((_attribute_state & M2MReportHandler::Pmin) != M2MReportHandler::Pmin || _pmin_exceeded) { report(); } } void M2MReportHandler::report() { tr_debug("M2MReportHandler::report()"); if(_current_value != _last_value && _notify) { tr_debug("M2MReportHandler::report()- send with PMIN"); _pmin_exceeded = false; _pmax_exceeded = false; _notify = false; _observer.observation_to_be_sent(_changed_instance_ids); _changed_instance_ids.clear(); _pmax_timer.stop_timer(); } else { if (_pmax_exceeded) { tr_debug("M2MReportHandler::report()- send with PMAX"); _observer.observation_to_be_sent(_changed_instance_ids, true); _changed_instance_ids.clear(); } else { tr_debug("M2MReportHandler::report()- no need to send"); } } handle_timers(); _last_value = _current_value; } void M2MReportHandler::handle_timers() { tr_debug("M2MReportHandler::handle_timers()"); uint64_t time_interval = 0; if ((_attribute_state & M2MReportHandler::Pmin) == M2MReportHandler::Pmin) { if (_pmin == _pmax) { _pmin_exceeded = true; } else { _pmin_exceeded = false; time_interval = (uint64_t) ((uint64_t)_pmin * 1000); tr_debug("M2MReportHandler::handle_timers() - Start PMIN interval: %d", (int)time_interval); _pmin_timer.start_timer(time_interval, M2MTimerObserver::PMinTimer, true); } } if ((_attribute_state & M2MReportHandler::Pmax) == M2MReportHandler::Pmax) { if (_pmax > 0) { time_interval = (uint64_t) ((uint64_t)_pmax * 1000); tr_debug("M2MReportHandler::handle_timers() - Start PMAX interval: %d", (int)time_interval); _pmax_timer.start_timer(time_interval, M2MTimerObserver::PMaxTimer, true); } } } bool M2MReportHandler::check_attribute_validity() { bool success = true; if ((_attribute_state & M2MReportHandler::Pmax) == M2MReportHandler::Pmax && ((_pmax >= -1.0) && (_pmin > _pmax))) { success = false; } float low = _lt + 2 * _st; if ((_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt && (low >= _gt)) { success = false; } return success; } void M2MReportHandler::stop_timers() { tr_debug("M2MReportHandler::stop_timers()"); _pmin_exceeded = false; _pmin_timer.stop_timer(); _pmax_exceeded = false; _pmax_timer.stop_timer(); tr_debug("M2MReportHandler::stop_timers() - out"); } void M2MReportHandler::set_default_values() { tr_debug("M2MReportHandler::set_default_values"); _pmax = -1.0; _pmin = 1.0; _gt = 0.0f; _lt = 0.0f; _st = 0.0f; _high_step = 0.0f; _low_step = 0.0f; _pmin_exceeded = false; _pmax_exceeded = false; _last_value = -1.0f; _attribute_state = 0; _changed_instance_ids.clear(); } bool M2MReportHandler::check_threshold_values() { tr_debug("M2MReportHandler::check_threshold_values"); tr_debug("Current value: %f", _current_value); tr_debug("High step: %f", _high_step); tr_debug("Low step: %f", _low_step); tr_debug("Less than: %f", _lt); tr_debug("Greater than: %f", _gt); tr_debug("Step: %f", _st); bool can_send = false; // Check step condition if ((_attribute_state & M2MReportHandler::St) == M2MReportHandler::St) { if ((_current_value >= _high_step || _current_value <= _low_step)) { can_send = true; } else { if ((_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt || (_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt ) { can_send = check_gt_lt_params(); } else { can_send = false; } } } else { can_send = check_gt_lt_params(); } tr_debug("M2MReportHandler::check_threshold_values - value in range = %d", (int)can_send); return can_send; } bool M2MReportHandler::check_gt_lt_params() { tr_debug("M2MReportHandler::check_gt_lt_params"); bool can_send = false; // GT & LT set. if ((_attribute_state & (M2MReportHandler::Lt | M2MReportHandler::Gt)) == (M2MReportHandler::Lt | M2MReportHandler::Gt)) { if (_current_value > _gt || _current_value < _lt) { can_send = true; } else { can_send = false; } } // Only LT else if ((_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt && (_attribute_state & M2MReportHandler::Gt) == 0 ) { if (_current_value < _lt) { can_send = true; } else { can_send = false; } } // Only GT else if ((_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt && (_attribute_state & M2MReportHandler::Lt) == 0 ) { if (_current_value > _gt) { can_send = true; } else { can_send = false; } } // GT & LT not set. else { can_send = true; } tr_debug("M2MReportHandler::check_gt_lt_params - value in range = %d", (int)can_send); return can_send; } uint8_t M2MReportHandler::attribute_flags() { return _attribute_state; }