Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 4896

Advanced users • Re: Has anyone ever deployed a reliable BLE Peripheral on a Zero 2?

$
0
0
I got a lot of help from others to integrate a temperature device e.g Xiaomi & Qingping modified per Christophel and Victor https://github.com/pvvx/ATC_MiThermometer/ so here's the payback.
The code is run in a separate thread so modify your entry point from Monitor(void) which does the basic setup.
The main thread calls DbusSetup(DBusError derr) when it wants and the sleep allows dbus to reset.
I've left the Decode() function in this in case it is useful so the output data is readbt formatted as 4+4+4 temp+RH+mV,
otherwise use data[2]. I've also left a lot of annotations in.
Hope it helps Please advise if my code raises issues (I won't answer) but it is clean under Valgrind and runs perfectly on a headless zero.

Code:

/* * File:Blez.h * V1.028Oct24 Common version * Credit: deepo @ https://forums.raspberrypi.com/viewtopic.php?p=2130050&hilit=deepo&sid=5ab8dc7366362afcd4d901591106ce28#p2130050*/#ifndef BLEZ_H#define BLEZ_H#include <ctime>#include <dbus/dbus.h>#include <fstream>#include <iostream>#include <string>#include <sys/reboot.h>#include <thread>#include <unistd.h>class Blez{private:bool address = false;bool bluname = false;bool rssisig = false;bool service = false;DBusConnection* conn;DBusError derr;std::string combo;std::string data[7];std::string mac;std::string svalue;void ActionMsg(void);void DbusSetup(DBusError);void Decode(std::string);void Error(std::string);void Extracter(DBusMessageIter*, int);std::string FindMAC(void);void Output(int);void Recurser(DBusMessageIter*);void UnpackMsg(DBusMessage*);public:std::string readbt = "-99000009999";void Monitor(void);};#endif

Code:

/** File:Blez.cpp* V1.230Oct24* Credit: deepo @ https://forums.raspberrypi.com/viewtopic.php?p=2130050&hilit=deepo&sid=5ab8dc7366362afcd4d901591106ce28#p2130050* And many others*/#include "Blez.h"//------------------------------------------------------------------------------//Check for bus errorsvoid Blez::Error(std::string derr){dbus_connection_unref(conn);std::cout<<"Error: "<<derr<<std::endl;exit(0);}//------------------------------------------------------------------------------void Blez::Decode(std::string data){if(data == "") readbt = "-99500009999";else{int deghumbatt;std::string target = "";target = data.substr(2, 2) + data.substr(0, 2);deghumbatt = std::stoi(target, nullptr, 16)+5;//round updeghumbatt /= 10;target = std::to_string(deghumbatt);if(target.size() < 4) target.insert(0, (4 - target.size()), '0');readbt = target;target = data.substr(6, 2) + data.substr(4, 2);deghumbatt = std::stoi(target, nullptr, 16);deghumbatt /= 10;target = std::to_string(deghumbatt);if(target.size() < 4) target.insert(0, (4 - target.size()), '0');readbt += target;target = data.substr(10, 2) + data.substr(8, 2);deghumbatt = std::stoi(target, nullptr, 16);target = std::to_string(deghumbatt);if(target.size() < 4) target.insert(0, (4 - target.size()), '0');readbt += target;}}//------------------------------------------------------------------------------void Blez::Output(int type){switch(type){case 101://d dictcombo = svalue = "";break;case 97://a arraybreak;case 118://v variantcombo+=" : ";break;default:combo += svalue;if(type == 121) data[2] += svalue;if(address) {address = false; data[0] = svalue;}if(bluname) {bluname = false; data[1] = svalue;}if(service) {service = false;}if(rssisig) {rssisig = false; data[3] = svalue;}if(svalue == "Address") address = true;//device MAC addressif(svalue == "Name") bluname = true;//device identityif((svalue == "ServiceData") ||   (svalue == "ManufacturerData")) service = true;if(svalue == "RSSI") rssisig = true;//signal level}svalue = "";}//------------------------------------------------------------------------------void Blez::Extracter(DBusMessageIter* iter, int type){DBusBasicValue bvalue; dbus_message_iter_get_basic(iter, &bvalue);switch(type){case 121://Byte (8-bit unsigned int){int vbyt = bvalue.byt;char temp[3];sprintf(temp, "%02X", vbyt);svalue += std::string(temp);}break;case 98://bool valuessvalue = std::to_string(bvalue.bool_val);break;case 110://16-bit signed intsvalue = std::to_string(bvalue.i16);break;case 113://16-bit unsigned intsvalue = std::to_string(bvalue.u16);break;case DBUS_TYPE_INT32:svalue = std::to_string(bvalue.i32);break;case DBUS_TYPE_UINT32:svalue = std::to_string(bvalue.u32);break;case DBUS_TYPE_INT64:svalue = std::to_string(bvalue.i64);break;case DBUS_TYPE_UINT64:svalue = std::to_string(bvalue.u64);break;case DBUS_TYPE_DOUBLE:svalue = std::to_string(bvalue.dbl);break;case 's'://string/*Typical allocations: * Address(MAC), AddressType, Name, Alias, Paired, Trusted, * Blocked, LegacyPairing, RSSI, Connected, UUID, Adapter, * ManufacturerData, ServiceData, ServicesResolved, Properties*/case 'o'://object path (string)case 'g'://object path (string)svalue = std::string(bvalue.str);break;default:std::cout<<"type "<<type<<" fault at 123 in Blez.cpp"<<std::endl;svalue = "";}//next line outputs basic type values://if(svalue.length() > 0) std::cout<<type<<"basic-type value= "<<svalue<<std::endl;}//------------------------------------------------------------------------------void Blez::Recurser(DBusMessageIter* iter0){int type;DBusMessageIter iter1;dbus_message_iter_recurse(iter0, &iter1);while ((type = dbus_message_iter_get_arg_type(&iter1)) != DBUS_TYPE_INVALID){switch(type){case 97://array (& reset){int count = dbus_message_iter_get_element_count(&iter1);for(int i = 0; i < count; ++i){Recurser(&iter1);count=0;}break;}case 101://dictcase 118://variantOutput(type);Recurser(&iter1);break;default:Extracter(&iter1, type);Output(type);}dbus_message_iter_next(&iter1);}}//------------------------------------------------------------------------------void Blez::UnpackMsg(DBusMessage* message)//sets arg for Recurser(){//next line is optional message separator://std::cout<<"##########################################"<<std::endl;//next two lines output signature//std::string sig = std::string(dbus_message_get_signature(message));//std::cout<<sig<<": signature crosscheck"<<std::endl;data[0] = data[1] = data[2] = "";DBusMessageIter iter0;dbus_message_iter_init(message, &iter0);int type;while ((type = dbus_message_iter_get_arg_type(&iter0)) != DBUS_TYPE_INVALID){if(type == DBUS_TYPE_ARRAY) Recurser(&iter0);//dismisses 1st arraydbus_message_iter_next(&iter0);}}//------------------------------------------------------------------------------void Blez::ActionMsg(void)// Main loop{bool loop = true;DBusMessage* msg;DBusError derr;dbus_error_init(&derr);while(loop){if(dbus_connection_read_write(conn, 10000))//returns FALSE if connection closed{msg = dbus_connection_pop_message(conn);if(msg == NULL){loop = false;continue;}UnpackMsg(msg);dbus_message_unref(msg);if(!data[0].empty())//clean display on 1st run{//next line outputs BT device MAC address//std::cout<<"MAC address = "<<data[0]<<std::endl;//next line outputs BTdevice name//std::cout<<"Device name = "<<data[1]<<std::endl;//next line outputs service data//std::cout<<"Service data = "<<data[2]<<std::endl;//next line outputs signal strength//std::cout<<"Signal strength = "<<data[3]<<std::endl;}//std::cout<<"  mac in code  "<<mac<<std::endl;if(data[0] == mac){data[2].erase(0, 12);Decode(data[2]);}}else reboot(RB_AUTOBOOT);}return;}//------------------------------------------------------------------------------void Blez::DbusSetup(DBusError derr){DBusMessage* msg;dbus_connection_set_exit_on_disconnect(conn, false);msg = dbus_message_new_method_call("org.bluez", "/org/bluez/hci0",   "org.bluez.Adapter1", "StartDiscovery");bool dsend = dbus_connection_send(conn, msg, NULL);if(!dsend) Error("NO MEMORY - NO METHOD");dbus_message_unref(msg);const char* match_rule = "type='signal',interface='org.freedesktop.DBus.ObjectManager',member='InterfacesAdded'";dbus_bus_add_match(conn, match_rule, &derr);dbus_connection_flush(conn);if(dbus_error_is_set(&derr)) Error("NO MATCH");ActionMsg();msg = dbus_message_new_method_call("org.bluez", "/org/bluez/hci0",   "org.bluez.Adapter1", "StopDiscovery");dbus_connection_send(conn, msg, NULL);dbus_message_unref(msg);return;}//------------------------------------------------------------------------------void Blez::Monitor(void){"mac = enter device MAC address here"DBusError derr;dbus_error_init(&derr);conn = dbus_bus_get(DBUS_BUS_SYSTEM, &derr);if(conn == NULL) Error("NO BUS");while(true){DbusSetup(derr);std::this_thread::sleep_for(std::chrono::seconds(50));}}

Statistics: Posted by Hillybilly — Wed Nov 27, 2024 10:38 am



Viewing all articles
Browse latest Browse all 4896

Trending Articles