Tile Trackers

Has anyone tried to / made a presence sensor out of the tile sensors before ?

1 Like

I have a couple of these.. some very important things to note..

  1. they use Bluetooth, so don't work natively with the hub as it doesn't have bluetooth. So you'll need a program on a separate computer (pi, old laptop etc) that does a BLE Scan and then lets the Hub know they're in range.

  2. Once "paired" with a phone app they are pretty much undetectable by a simple "BLE Scan".

To get mine to work I (a year ago) paired them with the Tile phone app, and then uninstalled the app... once the app is no longer running they can be "found" using a BLE scan.

I have since bought a similar "TrackR" device, and these also behave the the same way - the app on my phone has to be uninstalled or force-closed.

1 Like

While not specifically Tile, I did some work on BLE and presence detection using a pi. I abandoned the idea because it would require several receivers in each location and the cost began to be too high for the application. The range of BLE is, from my perspective, too low to be of much use for presence detection.

Anyone looked into this yet?

https://www.xandem.com/product

No price listing on the website is a bad sign.

1 Like

That didn't used to be the case. Product was also available a year ago. Now you have to contact them re: product availability - also not a good sign.

Edit - also FYI, early backers received product in 2016. And most of the initial reviews were reasonable.

I contacted them.

We are not selling our kits directly to the general public at this time which is why pricing is not available via the website. That may change in the future, so please keep an eye on us via our email announcements. Thank you.

No recommend vendors or however you're supposed to acquire them. Yawn, moving on.

@andrew.rowbottom
Glad to hear someone got these. I assume you are using them for room presence or house presence?
Did you get the premium service with "smart alerts" so when the tile is out of range it alerts you? I would be interested in that. Would also be nice if that capability could be tied to HE which I guess maybe possible if you use tasker bluetooth detection on your phone? (and assuming you always take your phone with you).

I'm considering to buy some of these but I see they (Tile) have not really mentioned anything about using IFTTT, open API, or others (Alexi/Google) integrations. So I'm looking at the alternative ways to get this truly smart.

I created an Arduino IDE Hubitat Tile presence device using an Adafruit Huzzah32, which includes both Wifi and Bluetooth Low Energy on the board. The device also requires using the ST_Anything Parent Device code and knowing the MAC address of the Tile. (You can use the BLE_scan example code to get the Tile MAC address.) You can easily modify the code to allow the Huzzah to using search for additional Tiles.

//******************************************************************************************
// 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
// - 1 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".
//
// 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

//******************************************************************************************
//******************************************************************************************
// 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"; // <---You must edit this line with the MAC address of your device
BLEScan* pBLEScan;

//****************************************************************************************************************************
//NodeMCU-32s ESP32 Pin Definitions (just for reference from ..hardware\espressif\esp32\variants\nodemcu-32s\pins_arduino.h)
//****************************************************************************************************************************
//#define LED_BUILTIN 2
//#define BUILTIN_LED 2
//
//#define A0 = 36;
//#define A3 = 39;
//#define A4 = 32;
//#define A5 = 33;
//#define A6 = 34;
//#define A7 = 35;
//#define A10 = 4;
//#define A11 = 0;
//#define A12 = 2;
//#define A13 = 15;
//#define A14 = 13;
//#define A15 = 12;
//#define A16 = 14;
//#define A17 = 27;
//#define A18 = 25;
//#define A19 = 26;

//******************************************************************************************
//Define which Arduino Pins will be used for each device
//******************************************************************************************
//"RESERVED" pins for ESP32 - best to avoid
//#define PIN_0_RESERVED 0 //reserved ESP32 boot/program upload
//#define PIN_1_RESERVED 1 //reserved ESP32 for TX0
//#define PIN_3_RESERVED 3 //reserved ESP32 for RX0
//#define PIN_6_RESERVED 6 //reserved ESP32 for flash
//#define PIN_7_RESERVED 7 //reserved ESP32 for flash
//#define PIN_8_RESERVED 8 //reserved ESP32 for flash
//#define PIN_9_RESERVED 9 //reserved ESP32 for flash
//#define PIN_10_RESERVED 10 //reserved ESP32 for flash
//#define PIN_11_RESERVED 11 //reserved ESP32 for flash

//Digital Pins
#define PIN_PRESENCE_1 13 //SmartThings Capabilty "Presence Sensor""
#define PIN_PRESENCE_OUT1 14 //Jumper output to PIN_PRESENCE_1 input

//******************************************************************************************
//ESP32 WiFi Information
//******************************************************************************************
String str_ssid = ""; // <---You must edit this line!
String str_password = ""; // <---You must edit this line!
IPAddress ip(10, 0, 1, 29); // Device IP Address // <---You must edit this line!
IPAddress gateway(10, 0, 1, 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(10, 0, 1, 15); // hubitat hub ip // <---You must edit this line!
const unsigned int hubPort = 39501; // hubitat hub port

bool isPresent1 = false;
int ble1NotFoundCount = 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_OUT1,OUTPUT);
digitalWrite(PIN_PRESENCE_OUT1,HIGH); //Initialize to notpresent

//******************************************************************************************
//Setup Bluetooth Low Energy scan
//Begin scanning for BLE devices
Serial.begin(115200);
BLEDevice::init("BLEScanner");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // 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);

//*****************************************************************************
// 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);

//*****************************************************************************
//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;
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(!ble1Found) {
ble1NotFoundCount++;
if(ble1NotFoundCount >= 5 ) {
isPresent1 = false;
Serial.printf("BLE1 not found; isPresent1 is false.\n");
digitalWrite(PIN_PRESENCE_OUT1, HIGH);
ble1NotFoundCount = 0;
}
}

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

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

2 Likes

@scottmil what’s the reason/need you are writing to digital pins when the presence changes? How would this work if you expanded to multiple tiles? Just use different pins?

Thanks!

Thank you for your question. When I wrote the code I framed my logic between an "output" of a sensor device (the Tile presence sensor) and connected the a SmartThings/Hubitat "input". After you stirred my thinking, I probably could eliminate the input pins and read the state of the output pins directly.

1 Like

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

In case that helps: added integration for both Tile tracker's cloud APIs and Generic Bluetooth presence detection. Using both for my Tile Pro and Tile Mate devices.

1 Like