Commit 548acfae authored by apapkovskiy's avatar apapkovskiy
Browse files

Added BLE PIR sensors scanner

parent 38e1b7ac
......@@ -12,7 +12,7 @@ prime/
.idea/
# visual studio code
/.vscode/
/**/.vscode/
/.settings/
/.history/
......@@ -20,7 +20,7 @@ prime/
middleware_build/
# aws sdk git
/aws-iot-device-sdk-cpp/
/build/
/**/aws-iot-device-sdk-cpp/
/**/build/
.ssh/
......@@ -25,7 +25,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
if (UNIX AND NOT APPLE)
# Prefer pthread if found
set(THREADS_PREFER_PTHREAD_FLAG ON)
set(CUSTOM_COMPILER_FLAGS "-fno-exceptions -Wall -Werror")
set(CUSTOM_COMPILER_FLAGS "-Wall -Werror")
# Fof REST API set(CUSTOM_COMPILER_FLAGS "-fno-exceptions -Wall -Werror")
elseif (APPLE)
set(CUSTOM_COMPILER_FLAGS "-fno-exceptions -Wall -Werror")
elseif (WIN32)
......@@ -37,7 +38,7 @@ endif ()
################################
set(PUB_SUB_SAMPLE_TARGET_NAME pub-sub-sample)
# Add Target
add_executable(${PUB_SUB_SAMPLE_TARGET_NAME} "${PROJECT_SOURCE_DIR}/PubSub.cpp;${PROJECT_SOURCE_DIR}/../aws-iot-device-sdk-cpp/common/ConfigCommon.cpp")
add_executable(${PUB_SUB_SAMPLE_TARGET_NAME} "${PROJECT_SOURCE_DIR}/PubSub.cpp;${PROJECT_SOURCE_DIR}/ble_PIR_scanner.cpp;${PROJECT_SOURCE_DIR}/ble_edge.cpp;${PROJECT_SOURCE_DIR}/../aws-iot-device-sdk-cpp/common/ConfigCommon.cpp")
# Add Target specific includes
target_include_directories(${PUB_SUB_SAMPLE_TARGET_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/../aws-iot-device-sdk-cpp/common)
......@@ -46,12 +47,20 @@ target_include_directories(${PUB_SUB_SAMPLE_TARGET_NAME} PUBLIC ${PROJECT_SOURCE
# Configure Threading library
find_package(Threads REQUIRED)
# Configure cpprestsdk library
find_package(Boost REQUIRED system)
#find_package(cpprestsdk REQUIRED NAMES cpprestsdk cpprest)
find_library(cpprestsdk-lib cpprest)
message(STATUS "cpprestsdk-lib = ${cpprestsdk-lib}")
# Add SDK includes
target_include_directories(${PUB_SUB_SAMPLE_TARGET_NAME} PUBLIC ${CMAKE_BINARY_DIR}/${DEPENDENCY_DIR}/rapidjson/src/include)
target_include_directories(${PUB_SUB_SAMPLE_TARGET_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/../aws-iot-device-sdk-cpp/include)
target_link_libraries(${PUB_SUB_SAMPLE_TARGET_NAME} PUBLIC "Threads::Threads")
target_link_libraries(${PUB_SUB_SAMPLE_TARGET_NAME} PUBLIC ${SDK_TARGET_NAME})
target_link_libraries(${PUB_SUB_SAMPLE_TARGET_NAME} PUBLIC bluetooth)
target_link_libraries(${PUB_SUB_SAMPLE_TARGET_NAME} PUBLIC cpprest ${Boost_SYSTEM_LIBRARY})
# Copy Json config file
add_custom_command(TARGET ${PUB_SUB_SAMPLE_TARGET_NAME} POST_BUILD
......
......@@ -36,42 +36,41 @@
#include "ConfigCommon.hpp"
#include "PubSub.hpp"
#include "ble_PIR_scanner.hpp"
#define LOG_TAG_PUBSUB "[Sample - PubSub]"
#define MESSAGE_COUNT 5
#define SDK_SAMPLE_TOPIC "sdk/test/cpp"
using namespace rigado;
namespace awsiotsdk {
namespace samples {
ResponseCode PubSub::RunPublish(int msg_count) {
std::cout << std::endl
<< "******************************Entering Publish with no queuing delay unless queue is full!!**************************"
<< std::endl;
int PubSub::RunPublish(std::string payload) {
ResponseCode rc;
uint16_t packet_id = 0;
int itr = 1;
util::String p_topic_name_str = SDK_SAMPLE_TOPIC;
do {
util::String payload = "Hello from SDK : ";
payload.append(std::to_string(itr));
do {
std::cout << "Publish Payload : " << payload << std::endl;
std::unique_ptr<Utf8String> p_topic_name = Utf8String::Create(p_topic_name_str);
rc = p_iot_client_->PublishAsync(std::move(p_topic_name), false, false, mqtt::QoS::QOS1,
payload, nullptr, packet_id);
if (ResponseCode::SUCCESS == rc) {
cur_pending_messages_++;
total_published_messages_++;
std::cout << "Publish Packet Id : " << packet_id << std::endl;
return 0;
} else if (ResponseCode::ACTION_QUEUE_FULL == rc) {
itr--;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
} else {
return -1;
}
} while (++itr <= msg_count && (ResponseCode::SUCCESS == rc || ResponseCode::ACTION_QUEUE_FULL == rc));
} while (ResponseCode::ACTION_QUEUE_FULL == rc);
return rc;
return 0;
}
ResponseCode PubSub::SubscribeCallback(util::String topic_name,
......@@ -238,8 +237,7 @@ namespace awsiotsdk {
}
util::String client_id_tagged = ConfigCommon::base_client_id_;
// client_id_tagged.append("_pub_sub_tester_");
// client_id_tagged.append(std::to_string(rand()));
std::unique_ptr<Utf8String> client_id = Utf8String::Create(client_id_tagged);
rc = p_iot_client_->Connect(ConfigCommon::mqtt_command_timeout_, ConfigCommon::is_clean_session_,
......@@ -249,45 +247,9 @@ namespace awsiotsdk {
return rc;
}
rc = Subscribe();
if (ResponseCode::SUCCESS != rc) {
AWS_LOG_ERROR(LOG_TAG_PUBSUB, "Subscribe failed. %s", ResponseHelper::ToString(rc).c_str());
} else {
// Test with delay between each action being queued up
rc = RunPublish(MESSAGE_COUNT);
if (ResponseCode::SUCCESS != rc) {
std::cout << std::endl << "Publish runner failed. " << ResponseHelper::ToString(rc) << std::endl;
AWS_LOG_ERROR(LOG_TAG_PUBSUB, "Publish runner failed. %s",
ResponseHelper::ToString(rc).c_str());
p_iot_client_->Disconnect(ConfigCommon::mqtt_command_timeout_);
}
std::cout << ResponseHelper::ToString(rc) << std::endl;
if (ResponseCode::SUCCESS == rc) {
//Sleep for 10 seconds and wait for all messages to be received
int cur_sleep_sec_count = 0;
do {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (0 == cur_pending_messages_) {
break;
}
cur_sleep_sec_count++;
std::cout << "Waiting!!! " << cur_sleep_sec_count << std::endl;
} while (cur_sleep_sec_count < 100);
}
do {
rc = Unsubscribe();
if (ResponseCode::ACTION_QUEUE_FULL == rc) {
std::cout << "Message queue full on Unsub, waiting!!!" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
} while (ResponseCode::ACTION_QUEUE_FULL == rc);
if (ResponseCode::SUCCESS != rc) {
AWS_LOG_ERROR(LOG_TAG_PUBSUB, "Unsubscribe failed. %s",
ResponseHelper::ToString(rc).c_str());
}
}
ble_scanner_cb_t p_cb = std::bind(&PubSub::RunPublish, this, std::placeholders::_1);
//rc = RunPublish(MESSAGE_COUNT);
ble_start(p_cb);
rc = p_iot_client_->Disconnect(ConfigCommon::mqtt_command_timeout_);
if (ResponseCode::SUCCESS != rc) {
......@@ -295,9 +257,7 @@ namespace awsiotsdk {
}
std::cout << std::endl << "*************************Results**************************" << std::endl;
std::cout << "Pending published messages : " << cur_pending_messages_ << std::endl;
std::cout << "Total published messages : " << total_published_messages_ << std::endl;
std::cout << "Exiting Sample!!!!" << std::endl;
return ResponseCode::SUCCESS;
}
}
......
......@@ -35,7 +35,7 @@ namespace awsiotsdk {
std::atomic_int total_published_messages_;
std::shared_ptr<MqttClient> p_iot_client_;
ResponseCode RunPublish(int msg_count);
int RunPublish(std::string str);
ResponseCode SubscribeCallback(util::String topic_name,
util::String payload,
std::shared_ptr<mqtt::SubscriptionHandlerContextData> p_app_handler_data);
......
/**
* @file ble.cpp
* @brief Bluez BLE scanner
*
*/
#include <chrono>
#include <cstring>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include "util/logging/Logging.hpp"
#include "util/logging/LogMacros.hpp"
#include "util/logging/ConsoleLogSystem.hpp"
#include "util/memory/stl/String.hpp"
#include <iostream>
#include "ble_PIR_scanner.hpp"
#define LOG_TAG_BLE "[Sample - BLE]"
#define BLE_ADV_NAME_SHORT 0x08
#define BLE_ADV_NAME_COMPLETE 0x09
#define BLE_DEFAULT_HCI 0x01
namespace rigado {
static struct hci_filter original_filter;
static int device_handle;
static size_t calcDecodeLength(const char* b64input) { //Calculates the length of a decoded string
size_t len = strlen(b64input),
padding = 0;
if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are =
padding = 2;
else if (b64input[len-1] == '=') //last char is =
padding = 1;
return (len*3)/4 - padding;
}
static int Base64Decode(const char* b64message, unsigned char** buffer, size_t* length) { //Decodes a base64 encoded string
BIO *bio, *b64;
size_t decodeLen = calcDecodeLength(b64message);
*buffer = (unsigned char*)malloc(decodeLen + 1);
(*buffer)[decodeLen] = '\0';
bio = BIO_new_mem_buf(b64message, -1);
b64 = BIO_new(BIO_f_base64());
bio = BIO_push(b64, bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
*length = BIO_read(bio, *buffer, strlen(b64message));
// *length == decodeLen length should equal decodeLen, else something went horribly wrong
if(*length != decodeLen){
AWS_LOG_ERROR(LOG_TAG_BLE, "Length (%d) should equal decodeLen (%d)", *length, decodeLen);
exit(1);
}
BIO_free_all(bio);
return (0); //success
}
static int cbor_PIR_parser(const uint8_t *p_buf){
// Example - A3:1:19:33:2C:2:A:18:2C:00
const uint8_t control_buf[] = { 0xA3, 0x01, 0x19, 0x33, 0x2C, 0x02, 0x0A, 0x18, 0x2C };
if(memcmp(p_buf, control_buf, sizeof(control_buf)) != 0){
return -1;
}
if(p_buf[sizeof(control_buf)] == 24){
return ((uint32_t)p_buf[sizeof(control_buf)] << 8) | (uint32_t)p_buf[sizeof(control_buf) + 1 ];
}
return p_buf[sizeof(control_buf)];
}
static int cmd_up(int device_handle, int dev_ind)
{
/* Start HCI device */
if (ioctl(device_handle, HCIDEVUP, dev_ind) < 0) {
if (errno == EALREADY)
return 0;
AWS_LOG_ERROR(LOG_TAG_BLE, "Can't init device hci%d: %s (%d)", dev_ind, strerror(errno), errno);
return -1;
}
return 0;
}
static int cmd_down(int device_handle, int dev_ind)
{
/* Stop HCI device */
if (ioctl(device_handle, HCIDEVDOWN, dev_ind) < 0) {
AWS_LOG_ERROR(LOG_TAG_BLE, "Can't down device hci%d: %s (%d)", dev_ind, strerror(errno), errno);
return -1;
}
return 0;
}
int ble_start(ble_scanner_cb_t cb){
socklen_t olen = sizeof(original_filter);
AWS_LOG_INFO(LOG_TAG_BLE, "BLE start scanning ...")
device_handle = hci_open_dev( BLE_DEFAULT_HCI ); // hci_get_route(NULL));
if ( device_handle < 0 ) {
AWS_LOG_ERROR(LOG_TAG_BLE, "Failed to open HCI device.");
return -1;
}
if (cmd_down(device_handle, BLE_DEFAULT_HCI) ||
cmd_up(device_handle, BLE_DEFAULT_HCI)){
goto ble_start_error;
}
if(hci_le_set_scan_parameters(device_handle, 0x01, htobs(0x0010), htobs(0x0010), 0x00, 0x00, 1000) < 0) {
AWS_LOG_ERROR(LOG_TAG_BLE, "Failed to set scan parameters: %s", strerror(errno));
goto ble_start_error;
}
if(hci_le_set_scan_enable(device_handle, 0x01, 0, 1000) < 0) {
AWS_LOG_ERROR(LOG_TAG_BLE, "Failed to enable scan: %s", strerror(errno));
goto ble_start_error;
}
// Save the current HCI filter
if(getsockopt(device_handle, SOL_HCI, HCI_FILTER, &original_filter, &olen) < 0)
{
AWS_LOG_ERROR(LOG_TAG_BLE, "Could not get socket options: %s", strerror(errno));
goto ble_start_error;
}
// Create and set the new filter
struct hci_filter new_filter;
hci_filter_clear(&new_filter);
hci_filter_set_ptype(HCI_EVENT_PKT, &new_filter);
hci_filter_set_event(EVT_LE_META_EVENT, &new_filter);
if(setsockopt(device_handle, SOL_HCI, HCI_FILTER, &new_filter, sizeof(new_filter)) < 0)
{
AWS_LOG_ERROR(LOG_TAG_BLE, "Could not set socket options: %s", strerror(errno));
goto ble_start_error;
}
uint8_t buf[HCI_MAX_EVENT_SIZE];
evt_le_meta_event * meta_event;
le_advertising_info * info;
int len;
while ( 1 ) {
len = read(device_handle, buf, sizeof(buf));
if ( len >= HCI_EVENT_HDR_SIZE ) {
meta_event = (evt_le_meta_event*)(buf+HCI_EVENT_HDR_SIZE+1);
if ( meta_event->subevent == EVT_LE_ADVERTISING_REPORT ) {
uint8_t reports_count = meta_event->data[0];
void * offset = meta_event->data + 1;
while ( reports_count-- ) {
info = (le_advertising_info *)offset;
char addr[18];
char device_name[31];
int32_t dev_RSSI;
int32_t index = 0;
ba2str(&(info->bdaddr), addr);
dev_RSSI = info->data[info->length];
memset(device_name, 0, sizeof(device_name));
while(index < info->length){
size_t data_len = info->data[index];
if(info->data[index + 1] == BLE_ADV_NAME_COMPLETE){
if(data_len >= sizeof(device_name))
data_len = sizeof(device_name);
memcpy(device_name, info->data + 2 + index, data_len - 1);
}
index += info->data[index] + 1;
}
if(memcmp(device_name, "~ow", 3) == 0){
uint8_t *p_buf64;
size_t len64;
std::stringstream ss;
// Skip '~' - device_name + 1
Base64Decode(device_name + 1, &p_buf64, &len64);
for(size_t i = 0; i < len64; i++){
printf("%X:", p_buf64[i]);
}
printf("\n");
ss << "{ sensors: [ {sensorMACAddr: \"" << addr << "\"," <<std::endl;
ss << "movements: " << cbor_PIR_parser(p_buf64) << "," <<std::endl;
ss << "RSSI: " << dev_RSSI << "}]}";
AWS_LOG_DEBUG(LOG_TAG_BLE, ss.str().c_str());
if(cb != NULL) {
if(cb(ss.str()) == -1)
goto ble_start_error;
}
}
offset = info->data + info->length + 2;
}
}
}
if(len < 1){
AWS_LOG_ERROR(LOG_TAG_BLE, "Could not read adv data: %s", strerror(errno));
goto ble_start_error;
}
}
return 0;
ble_start_error:
ble_stop();
return -1;
}
int ble_stop(void){
setsockopt(device_handle, SOL_HCI, HCI_FILTER, &original_filter, sizeof(original_filter));
if(hci_le_set_scan_enable(device_handle, 0x00, 1, 1000) < 0)
{
AWS_LOG_ERROR(LOG_TAG_BLE, "Disable scan failed: %s", strerror(errno));
}
hci_close_dev(device_handle);
return 0;
}
}
#pragma once
#include <iostream>
namespace rigado {
typedef std::function<int (std::string) > ble_scanner_cb_t;
int ble_stop(void);
int ble_start(ble_scanner_cb_t cb);
}
\ No newline at end of file
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <iostream>
using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
int ble_edge(void)
{
//http_client client(U("https://httpbin.org/"));
http_client client(U("http://172.27.1.242:8000/"));
// Build request URI and start the request.
uri_builder builder(U("/v1/msdt/1/mac"));
//uri_builder builder(U("/get"));
//builder.append_query(U("q"), U("cpprestsdk github"));
std::cout << "Uri: " << builder.to_string() << std::endl;
pplx::task<void> requestTask = client.request(methods::GET, builder.to_string())
// Handle response headers arriving.
.then([=](http_response response)
{
printf("Received response status code:%u\n", response.status_code());
web::json::value object = response.extract_json(true).get();
std::cout << object["data"] << std::endl;
});
// Wait for all the outstanding I/O to complete and handle any exceptions
try
{
requestTask.wait();
}
catch (const std::exception &e)
{
printf("Error exception:%s\n", e.what());
}
return 0;
}
\ No newline at end of file
......@@ -53,5 +53,25 @@ sudo snap set a71ch-aws-client a71ch-do-provisioning=DONT_PROVISIONING
## The main workflow
1. Install rigado-hsm-server snap
2. Install a71ch-aws-client snap
3. Set up pre-provisioning A71CH
4. Check publishing messages
\ No newline at end of file
3. !!! Very important. Check in the AWS account if there is a thing corresponding to the pre-provisioning device ID, delete it if it present
4. Set up pre-provisioning A71CH
5. Check publishing messages
## The current workflow (with some manual stuff)
Currently we are using only device with ID 04007002ffff00000000BB00000000000003 and NXP AWS demo account!!!
1. Install rigado-hsm-server snap
2. Install a71ch-aws-client snap
3. Stop pub-sub-sample service
```
sudo snap stop a71ch-aws-client.pub-sub-sample
```
4. Set up pre-provisioning A71CH
5. !!! Very important. Check in the AWS account if there is a thing corresponding to the pre-provisioning device ID, delete it if it present
6. Provision A71CH
7. Open autogenerated file $SNAP_COMMON/certs/SampleConfig.json and replace (this example is done for deviceID 04007002ffff00000000BB00000000000003, change the last digit for another deviceID):
```
- "client_id": "LightingDevices",
+ "client_id": "LightingDevices_348598032839380244606242920424862583357443",
```
samples/PubSub/PubSub.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/samples/PubSub/PubSub.cpp b/samples/PubSub/PubSub.cpp
index 651aa19..bd221aa 100644
--- a/samples/PubSub/PubSub.cpp
+++ b/samples/PubSub/PubSub.cpp
@@ -238,8 +238,8 @@ namespace awsiotsdk {
}
util::String client_id_tagged = ConfigCommon::base_client_id_;
- client_id_tagged.append("_pub_sub_tester_");
- client_id_tagged.append(std::to_string(rand()));
+// client_id_tagged.append("_pub_sub_tester_");
+// client_id_tagged.append(std::to_string(rand()));
std::unique_ptr<Utf8String> client_id = Utf8String::Create(client_id_tagged);
rc = p_iot_client_->Connect(ConfigCommon::mqtt_command_timeout_, ConfigCommon::is_clean_session_,
@@ -305,7 +305,7 @@ namespace awsiotsdk {
int main(int argc, char **argv) {
std::shared_ptr<awsiotsdk::util::Logging::ConsoleLogSystem> p_log_system =
- std::make_shared<awsiotsdk::util::Logging::ConsoleLogSystem>(awsiotsdk::util::Logging::LogLevel::Info);
+ std::make_shared<awsiotsdk::util::Logging::ConsoleLogSystem>(awsiotsdk::util::Logging::LogLevel::Debug);
awsiotsdk::util::Logging::InitializeAWSLogging(p_log_system);
std::unique_ptr<awsiotsdk::samples::PubSub>
......@@ -8,3 +8,4 @@ sudo snap connect a71ch-aws-client:network-control :network-control
sudo snap connect a71ch-aws-client:network-setup-control :network-setup-control
sudo snap connect a71ch-aws-client:lib-engine rigado-hsm-server:lib-engine
sudo snap connect a71ch-aws-client:lib-cert rigado-hsm-server:lib-cert
sudo snap connect a71ch-aws-client:bluetooth-control :bluetooth-control
name: a71ch-aws-client
version: '0.1'
version: '0.2ble'
summary: rigado-A71CH-AWS-client
description: |
NXP A71CH JRCP AWS Client for Rigado gateway
......@@ -24,6 +24,8 @@ parts:
build-packages:
- build-essential
- libssl-dev
- libcpprest-dev
- libbluetooth-dev
rigado-snapconf:
plugin: go
go-importpath: rigado-snapconf
......@@ -44,7 +46,7 @@ apps:
command: bin/start-pub-sub-sample
daemon: simple
restart-condition: always
plugs: &default-plugs [network-bind, network-control, network-setup-control, network, lib-cert, lib-engine]
plugs: &default-plugs [network-bind, network-control, network-setup-control, network, lib-cert, lib-engine, bluetooth-control]
provisioning:
environment:
OPENSSL_CONF: $SNAP/certs/opensslA71CH.cnf
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment