Tile Trackers

Per brianwilson's suggestion, I attempted to modify my code to write to the digital inputs directly to indicate presence changes, but I couldn't get it to work. After searching the internet, I found that other coders used the same technique of having a digital output pin set the state of a digital input pin that I used in my original code. I also expanded my code to search for a second Tile (see below).


//******************************************************************************************
// File: ST_Anything_TilePresence_ESP32WiFi.ino
// Authors: Scott Miller adapted from code by Dan G Ogorchock & Daniel J Ogorchock (Father and Son)
//
// Summary: This Arduino Sketch, along with the ST_Anything library and the revised SmartThings
// library, demonstrates the ability of an Adafruit Huzzah32 to
// implement a Tile presence sensor for integration into SmartThings/Hubitat.
// The ST_Anything library takes care of all of the work to schedule device updates
// as well as all communications with the Adafruint Huzzah32's WiFi.
//
// ST_Anything_TilePresence_ESP32WiFi implements the following ST Capability
// - 2 x Presence device (reading digital input set by BLE scans)
//
// The Arduino example app BLEScan can be used to discover the MAC address of your Tile, which has a serviceUID "feed".
// ***Compiled sketch for ESP32 Dev Module with No OTA partition to increase memory size.
//
// Change History:
//
// Date Who What
// ---- --- ----
// 2019-10-12 Dan Ogorchock Original Creation
// 2020-02-10 Scott Miller Modified for sensing Tiles using Bluetooth Low Energy
// 2020-03-15 Scott Miller Added second presence sensor
// 2020-07-02 Scott Miller Increased Bluetooth power

//******************************************************************************************
//******************************************************************************************
// SmartThings Library for ESP32WiFi
//******************************************************************************************
#include <SmartThingsESP32WiFi.h>

//******************************************************************************************
// ST_Anything Library
//******************************************************************************************
#include <Constants.h> //Constants.h is designed to be modified by the end user to adjust behavior of the ST_Anything library
#include <Device.h> //Generic Device Class, inherited by Sensor and Executor classes
#include <Sensor.h> //Generic Sensor Class, typically provides data to ST Cloud (e.g. Temperature, Motion, etc...)
#include <InterruptSensor.h> //Generic Interrupt "Sensor" Class, waits for change of state on digital input
#include <PollingSensor.h> //Generic Polling "Sensor" Class, polls Arduino pins periodically
#include <Everything.h> //Master Brain of ST_Anything library that ties everything together and performs ST Shield communications

#include <IS_Presence.h> //Implements a Presence Sensor (IS) to monitor the status of a digital input pin

//******************************************************************************************
// ESP32_BLE Library
//******************************************************************************************
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

int scanTime = 5; //In seconds
std::string TILE_MAC_ADDRESS_1 = "c1:62:85:c0:84:5d"; // <---Put your first Tile Mac address here
std::string TILE_MAC_ADDRESS_2 = "c3:4f:e9:0c:11:32"; // <---Put your second Tile Mac address here
BLEScan* pBLEScan;

//****************************************************************************************************************************
//Huzzah ESP32 Pin Definitions
//****************************************************************************************************************************
//
//#define A0 26 //GPIO26
//#define A1 25 //GPIO25
//#define A2 34 //GPI34
//#define A3 39 //GPI39
//#define A4 36 //GPI36
//#define A5 4 //GPIO4
//#define A6 14 //GPIO14
//#define A7 32 //GPIO32
//#define A8 15 //GPIO15
//#define A9 33 //GPIO33
//#define A10 27 //GPIO27
//#define A11 12 //GPIO12
//#define A12 13 //GPIO13 and red LED
//#define D21 21 //GPIO21

//Digital Pins
#define PIN_PRESENCE_1 13 //SmartThings Capability "Presence Sensor"
#define PIN_PRESENCE_2 15 //SmartThings Capability "Presence Sensor"
#define PIN_PRESENCE_OUT1 14 //Jumper output to PIN_PRESENCE_1 input
#define PIN_PRESENCE_OUT2 21 //Jumper output to PIN_PRESENCE_2 input

//******************************************************************************************
//ESP32 WiFi Information
//******************************************************************************************
String str_ssid = "YOUR NETWORK SSID"; // <---You must edit this line!
String str_password = "YOUR PASSWORS"; // <---You must edit this line!
IPAddress ip(192, 168, 0, 234); // ESP32 Device IP Address // <---You must edit this line!
IPAddress gateway(192, 168, 0, 1); //router gateway // <---You must edit this line!
IPAddress subnet(255, 255, 255, 0); //LAN subnet mask // <---You must edit this line!
IPAddress dnsserver(8,8,8,8); //DNS server // <---You must edit this line!
const unsigned int serverPort = 8090; // port to run the http server on

// Hubitat Hub Information
IPAddress hubIp(192, 168, 0, 231); // hubitat hub ip // <---You must edit this line!
const unsigned int hubPort = 39501; // hubitat hub port

bool isPresent1 = false;
bool isPresent2 = false;
int ble1NotFoundCount = 0;
int ble2NotFoundCount = 0;
int numLoops = 0;

//******************************************************************************************
//st::Everything::callOnMsgSend() optional callback routine. This is a sniffer to monitor
// data being sent to ST. This allows a user to act on data changes locally within the
// Arduino sktech.
//******************************************************************************************
//void callback(const String &msg)
//{
// Serial.print(F("ST_Anything Callback: Sniffed data = "));
// Serial.println(msg);

//TODO: Add local logic here to take action when a device's value/state is changed

//Masquerade as the ThingShield to send data to the Arduino, as if from the ST Cloud (uncomment and edit following line)
//st::receiveSmartString("Put your command here!"); //use same strings that the Device Handler would send
//}

//******************************************************************************************
//Arduino Setup() routine
//******************************************************************************************
void setup()
{
//Set and initialize pins to read result of BLE scan
pinMode(PIN_PRESENCE_1,INPUT);
pinMode(PIN_PRESENCE_2,INPUT);
pinMode(PIN_PRESENCE_OUT1,OUTPUT);
pinMode(PIN_PRESENCE_OUT2,OUTPUT);
digitalWrite(PIN_PRESENCE_OUT1,HIGH); //Initialize to notpresent
digitalWrite(PIN_PRESENCE_OUT2,HIGH); //Initialize to notpresent

//******************************************************************************************
//Setup Bluetooth Low Energy scan
//Begin scanning for BLE devices
Serial.begin(115200);
BLEDevice::init("BLEScanner");
//BLEDevice::setPower(ESP_PWR_LVL_P9); //set maximum power
//Below power settings are from How to increase ESP32 BLE range · Issue #674 · nkolban/esp32-snippets · GitHub
esp_err_t errRc=esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT,ESP_PWR_LVL_P9);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV,ESP_PWR_LVL_P9);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_SCAN,ESP_PWR_LVL_P9);
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(10000);
pBLEScan->setWindow(10000); // less or equal setInterval value

//******************************************************************************************
//Declare each Device that is attached to the Arduino
// Notes: - For details on each device's constructor arguments below, please refer to the
// corresponding header (.h) and program (.cpp) files.
// - The name assigned to each device (1st argument below) must match the Groovy
// Device Handler names.
// - The new Composite Device Handler is comprised of a Parent DH and various Child
// DH's. The names used below MUST not be changed for the Automatic Creation of
// child devices to work properly. Simply increment the number by +1 for each duplicate
// device (e.g. presence1, presence2, presence3, etc...) You can rename the Child Devices
// in the ST Phone Application or change the Hubitat Device Label
//******************************************************************************************

//Interrupt Sensors
static st::IS_Presence sensor1(F("presence1"), PIN_PRESENCE_1, LOW, true, 1);
static st::IS_Presence sensor2(F("presence2"), PIN_PRESENCE_2, LOW, true, 1);

//*****************************************************************************
// Configure debug print output from each main class
//*****************************************************************************
st::Everything::debug=true;
st::Device::debug=true;
st::PollingSensor::debug=true;
st::InterruptSensor::debug=true;

//*****************************************************************************
//Initialize the "Everything" Class
//*****************************************************************************

//Create the SmartThings ESP32WiFi Communications Object
//STATIC IP Assignment - Recommended
st::Everything::SmartThing = new st::SmartThingsESP32WiFi(str_ssid, str_password, ip, gateway, subnet, dnsserver, serverPort, hubIp, hubPort, st::receiveSmartString);

//DHCP IP Assigment - Must set your router's DHCP server to provice a static IP address for this device's MAC address
//st::Everything::SmartThing = new st::SmartThingsESP32WiFi(str_ssid, str_password, serverPort, hubIp, hubPort, st::receiveSmartString);

//Run the Everything class' init() routine which establishes WiFi communications with SmartThings Hub
st::Everything::init();

//*****************************************************************************
//Add each sensor to the "Everything" Class
//*****************************************************************************
st::Everything::addSensor(&sensor1);
st::Everything::addSensor(&sensor2);

//*****************************************************************************
//Initialize each of the devices which were added to the Everything Class
//*****************************************************************************
st::Everything::initDevices();
}

//******************************************************************************************
//Arduino Loop() routine
//******************************************************************************************
void loop() {
BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
Serial.print("Devices found: ");
Serial.println(foundDevices.getCount());
int i;
bool ble1Found = false;
bool ble2Found = false;
for (i=0; i < foundDevices.getCount(); i++) {
BLEAdvertisedDevice advertisedDevice = foundDevices.getDevice(i);
if (advertisedDevice.getAddress().toString() == TILE_MAC_ADDRESS_1) {
ble1Found= true;
Serial.printf("BLE1 Advertised Device: %s \n", advertisedDevice.toString().c_str());
ble1NotFoundCount = 0;
if(!isPresent1) {
isPresent1 = true;
Serial.printf("BLE1 found; isPresent1 is true.\n");
digitalWrite(PIN_PRESENCE_OUT1, LOW);
}
}
if (advertisedDevice.getAddress().toString() == TILE_MAC_ADDRESS_2) {
ble2Found= true;
Serial.printf("BLE2 Advertised Device: %s \n", advertisedDevice.toString().c_str());
ble2NotFoundCount = 0;
if(!isPresent2) {
isPresent2 = true;
Serial.printf("BLE2 found; isPresent2 is true.\n");
digitalWrite(PIN_PRESENCE_OUT2, LOW);
}
}
}
if(!ble1Found) {
ble1NotFoundCount++;
if(ble1NotFoundCount >= 10 ) {
isPresent1 = false;
Serial.printf("BLE1 not found; isPresent1 is false.\n");
digitalWrite(PIN_PRESENCE_OUT1, HIGH);
ble1NotFoundCount = 0;
}
}
if(!ble2Found) {
ble2NotFoundCount++;
if(ble2NotFoundCount >= 10 ) {
isPresent2 = false;
Serial.printf("BLE2 not found; isPresent2 is false.\n");
digitalWrite(PIN_PRESENCE_OUT2, HIGH);
ble2NotFoundCount = 0;
}
}

pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory

//*****************************************************************************
//Execute the Everything run method which takes care of "Everything"
//*****************************************************************************
if (numLoops >= 5) { // execute st::Everything::run() every 5 loops
st::Everything::run();
numLoops = 0;
} else {
numLoops++;
}
delay(2000);
}

1 Like