updating configuration
This commit is contained in:
@@ -0,0 +1,336 @@
|
||||
#include "esphome.h"
|
||||
|
||||
#define BLE_PIN D1
|
||||
|
||||
class HappyBubblesDevice : public Component, public CustomMQTTDevice {
|
||||
protected:
|
||||
// char hostname[20] = "hall";
|
||||
const char* hostname = "hall";
|
||||
String buf = "";
|
||||
int txPower = -59;
|
||||
char ble_mac_addr[13];
|
||||
char ble_rssi [5];
|
||||
char ble_is_scan_resp [2];
|
||||
char ble_type [2];
|
||||
char ble_data[100];
|
||||
|
||||
char tx_power [3];
|
||||
char beacon_uuid [33];
|
||||
char beacon_major [5];
|
||||
char beacon_minor [5];
|
||||
char instance_id [13];
|
||||
char json_ble_send[500];
|
||||
char topic [130];
|
||||
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
uint8_t start;
|
||||
uint8_t end;
|
||||
uint8_t size;
|
||||
} ble_tok_t;
|
||||
|
||||
public:
|
||||
HappyBubblesDevice(const char* host_param) {
|
||||
hostname = host_param;
|
||||
}
|
||||
void setup() override
|
||||
{
|
||||
Serial.begin(115200);
|
||||
}
|
||||
void loop() override
|
||||
{
|
||||
while (Serial.available() > 0) {
|
||||
char inChar = Serial.read();
|
||||
|
||||
if (inChar == '\n') {
|
||||
//если буфер наполнен
|
||||
// parseData();
|
||||
char charBuf[120];
|
||||
buf.toCharArray(charBuf, 120);
|
||||
process_serial(charBuf);
|
||||
buf = "";
|
||||
}
|
||||
else if (inChar != '\r') {
|
||||
buf += inChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String getValue(String data, char separator, int index)
|
||||
{
|
||||
int found = 0;
|
||||
int strIndex[] = { 0, -1 };
|
||||
int maxIndex = data.length() - 1;
|
||||
|
||||
for (int i = 0; i <= maxIndex && found <= index; i++) {
|
||||
if (data.charAt(i) == separator || i == maxIndex) {
|
||||
found++;
|
||||
strIndex[0] = strIndex[1] + 1;
|
||||
strIndex[1] = (i == maxIndex) ? i + 1 : i;
|
||||
}
|
||||
}
|
||||
|
||||
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
|
||||
}
|
||||
|
||||
float calcDistance(int rssi, int txPower)
|
||||
{
|
||||
if (rssi == 0) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
float ratio = rssi * 1.0 / txPower;
|
||||
if (ratio < 1.0) {
|
||||
return pow(ratio, 10);
|
||||
}
|
||||
else {
|
||||
return (0.89976) * pow(ratio, 7.7095) + 0.111;
|
||||
}
|
||||
}
|
||||
|
||||
String floatToString(float x, byte precision = 2)
|
||||
{
|
||||
char tmp[50];
|
||||
dtostrf(x, 0, precision, tmp);
|
||||
return String(tmp);
|
||||
}
|
||||
|
||||
void process_serial(char *buf)
|
||||
{
|
||||
os_printf("********* got serial to process %d ** %s \n\r", strlen(buf), buf);
|
||||
char * pch;
|
||||
pch = strtok(buf, "|");
|
||||
int i = 0;
|
||||
|
||||
memset(ble_mac_addr, 0, 12);
|
||||
memset(ble_rssi, 0, 5);
|
||||
memset(ble_is_scan_resp, 0, 1);
|
||||
memset(ble_type, 0, 1);
|
||||
memset(ble_data, 0, 100);
|
||||
|
||||
while(pch != NULL)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
strcpy(ble_mac_addr, pch);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
strcpy(ble_rssi, pch);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
strcpy(ble_is_scan_resp, pch);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
strcpy(ble_type, pch);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
strcpy(ble_data, pch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
//os_printf("token: %s\n", pch);
|
||||
pch = strtok(NULL, "|");
|
||||
}
|
||||
|
||||
//basic filters
|
||||
//check mac is 12 chars
|
||||
int should_send = 0;
|
||||
if(strlen(ble_mac_addr) != 12)
|
||||
{
|
||||
os_printf("bad mac, not 12, %d, %s\n", strlen(ble_mac_addr), ble_mac_addr);
|
||||
should_send = 1;
|
||||
}
|
||||
//check mac is all hex
|
||||
if (!ble_mac_addr[strspn(ble_mac_addr, "0123456789abcdefABCDEF")] == 0)
|
||||
{
|
||||
os_printf("bad mac, not all hex %s\n", ble_mac_addr);
|
||||
should_send = 2;
|
||||
}
|
||||
//check data is all hex
|
||||
if (strlen(ble_data) < 8 || !ble_data[strspn(ble_data, "0123456789abcdefABCDEF")] == 0 )
|
||||
{
|
||||
os_printf("bad data %s\n", ble_data);
|
||||
should_send = 3;
|
||||
}
|
||||
//check rssi is all numbers
|
||||
if (strlen(ble_rssi) < 1 || !ble_rssi[strspn(ble_rssi, "-0123456789")] == 0)
|
||||
{
|
||||
os_printf("bad rssi %s\n", ble_rssi);
|
||||
should_send = 4;
|
||||
}
|
||||
//check scan_response is 0 or 1
|
||||
if (strlen(ble_is_scan_resp) < 1 || !ble_is_scan_resp[strspn(ble_is_scan_resp, "01")] == 0)
|
||||
{
|
||||
os_printf("bad scanresp %s\n", ble_is_scan_resp);
|
||||
should_send = 5;
|
||||
}
|
||||
//check ble_type is hex
|
||||
if (strlen(ble_type) < 1 || !ble_type[strspn(ble_type, "0123456789abcdefABCDEF")] == 0)
|
||||
{
|
||||
os_printf("bad type %s\n", ble_type);
|
||||
should_send = 6;
|
||||
}
|
||||
if(should_send == 0)
|
||||
{
|
||||
//os_printf("^^^^^^^^^GOT THROUGH FILTERS!\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
//os_printf("xxxxxxxxxxFAIL FILTERS! %d \r\n", should_send);
|
||||
//os_printf("=====%s || %s || %s || %s || %s ===DONE\n", ble_mac_addr, ble_rssi, ble_is_scan_resp, ble_type, ble_data);
|
||||
return;
|
||||
}
|
||||
|
||||
//what type of beacon is this?
|
||||
int beacon_type = 99;
|
||||
|
||||
// iterate through the beacon data, but easier if it is bytes
|
||||
uint8_t adv_bytes[strlen(ble_data)/2];
|
||||
|
||||
for(int i=0; i<(strlen(ble_data)/2); i++) {
|
||||
uint8_t d1 = 0;
|
||||
|
||||
if(ble_data[i*2] > '9') {
|
||||
d1 += ((ble_data[i*2] - 'a' + 10) * 0x10);
|
||||
}
|
||||
else {
|
||||
d1 += ((ble_data[i*2] - '0') * 0x10);
|
||||
}
|
||||
|
||||
if(ble_data[i*2+1] > '9') {
|
||||
d1 += ble_data[i*2+1] - 'a' + 10;
|
||||
}
|
||||
else {
|
||||
d1 += ble_data[i*2+1] - '0';
|
||||
}
|
||||
|
||||
adv_bytes[i] = d1;
|
||||
}
|
||||
|
||||
// start with 6 tokens
|
||||
ble_tok_t tokens[6];
|
||||
|
||||
uint8_t token_i = 0;
|
||||
int stop = 0;
|
||||
int pos = 0;
|
||||
while(!stop) {
|
||||
tokens[token_i].size = adv_bytes[pos];
|
||||
tokens[token_i].type = adv_bytes[pos+1];
|
||||
tokens[token_i].start = pos+2;
|
||||
tokens[token_i].end = pos+tokens[token_i].size;
|
||||
|
||||
/*
|
||||
printf("tok: %d, size: %02hhx, type: %02hhx, start: %d end: %d\n", token_i, tokens[token_i].size, tokens[token_i].type, tokens[token_i].start, tokens[token_i].end);
|
||||
for(int j=tokens[token_i].start; j<=tokens[token_i].end; j++) {
|
||||
printf("%02hhx", adv_bytes[j]);
|
||||
}
|
||||
printf("\n\n");
|
||||
*/
|
||||
pos = tokens[token_i].end + 1;
|
||||
if(pos >= sizeof(adv_bytes)) {
|
||||
stop = 1;
|
||||
}
|
||||
token_i++;
|
||||
}
|
||||
|
||||
// iterate through the tokens and determine what kind of beacon it is
|
||||
for(int i = 0; i <= token_i; i++) {
|
||||
// is iBeacon?
|
||||
if(tokens[i].type == 0xff
|
||||
&& adv_bytes[tokens[i].start] == 0x4c
|
||||
&& adv_bytes[tokens[i].start+1] == 0x00
|
||||
&& adv_bytes[tokens[i].start+2] == 0x02
|
||||
&& adv_bytes[tokens[i].start+3] == 0x15) {
|
||||
|
||||
beacon_type = 1; //ibeacon
|
||||
|
||||
//now extract uuid
|
||||
memset(beacon_uuid, 0, 33);
|
||||
memcpy(beacon_uuid, &ble_data[(tokens[i].start+4)*2], 32);
|
||||
beacon_uuid[32] = '\0';
|
||||
|
||||
//extract major
|
||||
memset(beacon_major, 0, 5);
|
||||
memcpy(beacon_major, &ble_data[(tokens[i].start+20)*2], 4);
|
||||
beacon_major[4] = '\0';
|
||||
|
||||
//extract minor
|
||||
memset(beacon_minor, 0, 5);
|
||||
memcpy(beacon_minor, &ble_data[(tokens[i].start+22)*2], 4);
|
||||
beacon_minor[4] = '\0';
|
||||
|
||||
//extract tx_power
|
||||
memset(tx_power, 0, 3);
|
||||
memcpy(tx_power, &ble_data[(tokens[i].start+24)*2], 2);
|
||||
tx_power[3] = '\0';
|
||||
|
||||
os_printf("^^^^^ ibeacon %s %s %s %s\n", beacon_uuid, beacon_major, beacon_minor, tx_power);
|
||||
}
|
||||
}
|
||||
|
||||
//add some filters to
|
||||
if(beacon_type == 0)
|
||||
{
|
||||
//os_printf("send some mqtt for eddystone %s ========\n", beacon_uuid);
|
||||
// sendMQTTeddystone(ble_mac_addr, beacon_uuid, instance_id, tx_power, ble_rssi);
|
||||
}
|
||||
else if(beacon_type == 1)
|
||||
{
|
||||
//os_printf("send some mqtt for ibeacon %s ========\n", beacon_uuid);
|
||||
sendMQTTibeacon(ble_mac_addr, beacon_uuid, beacon_major, beacon_minor, tx_power, ble_rssi);
|
||||
}
|
||||
|
||||
//os_printf("send some mqtt for mac %s =====%d===\n", ble_mac_addr, strlen(ble_mac_addr));
|
||||
// sendMQTTraw(ble_mac_addr, ble_rssi, ble_is_scan_resp, ble_type, ble_data);
|
||||
}
|
||||
|
||||
// void sendMQTTeddystone(char *mac, char *namespace, char *instance_id, char *tx_power, char *rssi)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
void sendMQTTibeacon(char* mac, char* uuid, char* major, char* minor, char* tx_power, char* rssi)
|
||||
{
|
||||
float distance = calcDistance(atoi(rssi), 0x50);
|
||||
String distanceStr = floatToString(distance, 10);
|
||||
|
||||
memset(json_ble_send, 0, 500);
|
||||
os_sprintf(json_ble_send, "{\"hostname\": \"%s\",\"beacon_type\": \"ibeacon\",\"id\": \"%s\",\"rssi\": %s,\"uuid\": \"%s\",\"major\": \"%s\",\"minor\": \"%s\",\"tx_power\": \"%s\", \"distance\": \"%s\"}", hostname, mac, rssi, uuid, major, minor, tx_power, distanceStr.c_str());
|
||||
memset(topic, 0, 130);
|
||||
os_sprintf(topic, "home/presence/%s", hostname);
|
||||
publish(topic, json_ble_send);
|
||||
}
|
||||
// void sendMQTTraw(char * mac, char * rssi, char * is_scan, char * type, char * data)
|
||||
// {
|
||||
// memset(json_ble_send, 0, 500);
|
||||
// os_sprintf(json_ble_send, "{\"hostname\": \"%s\",\"mac\": \"%s\",\"rssi\": %s,\"is_scan_response\": \"%s\",\"type\": \"%s\",\r\n\"data\": \"%s\"}", hostname, mac, rssi, is_scan, type, data);
|
||||
// memset(topic, 0, 130);
|
||||
// os_sprintf(topic, "happy-bubbles/ble/%s/raw/%s", hostname, mac);
|
||||
// // publish(topic, json_ble_send);
|
||||
// }
|
||||
};
|
||||
|
||||
class BleSwitch : public Component, public Switch {
|
||||
public:
|
||||
void setup() override
|
||||
{
|
||||
// This will be called by App.setup()
|
||||
pinMode(BLE_PIN, OUTPUT);
|
||||
write_state(true);
|
||||
}
|
||||
void write_state(bool state) override
|
||||
{
|
||||
digitalWrite(BLE_PIN, !state);
|
||||
publish_state(state);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user