├── README.md └── presence-control.script /README.md: -------------------------------------------------------------------------------- 1 | # mikrotik-presence-control 2 | Mikrotik router script for reliable detection of WiFi client and sending HTTP requests when devices are registered or unregistered from the network. 3 | This approach works very reliably with Apple iPhone, iPad and other devices that are not reachable with TCP or UDP, but are still registered in the network. 4 | 5 | ## How it Works 6 | 7 | Mikrotik scheduler calls presence control script with specified interval to check if desired devices are registered in WiFi network. 8 | When script detects device state change in the network, it will send HTTP request to a desired server to report that device is registered, same when device is no longer present in the WiFi network. 9 | To improve reliability with multiple access point setup, when device is registered script will send up to `arriveSendTimes` requests to the server, as it may happen that access point where device was unregistered sends leave event to the server after device is registered on another access point happened, resulting in device being treated as not present by the server. 10 | 11 | Tested on `RouterOS v6.45.1 (stable)` 12 | 13 | ## Installation and Configuration 14 | 15 | ### Configuration 16 | 17 | **Variables** 18 | 19 | * `arriveSendTimes` - number of times to send requests to a server when device is registered within WiFi network 20 | * `subjects` - array of subjects to check presence of, each entry contains `name`, `mac` and `state` 21 | * `name` - name of person who owns particular device, is optinal and is only used in when sending HTTP requests 22 | * `mac` - MAC adress of wathced device, should be in uppercase 23 | * `state` - internal state variable used for detecting state changes, should be set to 0 24 | 25 | **In-script Modification** 26 | 27 | Modify following lines based on your requirements, in current example it was used for reporting state to [homebridge-people-x](https://www.npmjs.com/package/homebridge-people-x) via webhooks: 28 | 29 | ``` 30 | :tool fetch mode=http http-method=post http-data="" url="http://homebridge:51828/?sensor=$name&state=false" 31 | ... 32 | :tool fetch mode=http http-method=post http-data="" url="http://homebridge:51828/?sensor=$name&state=true" 33 | ``` 34 | 35 | ### Installation 36 | 37 | From Mikrotik WebFig IDE: 38 | * Create new script `System` -> `Scripts` -> `Scripts tab` -> `Add New` 39 | * Set Name to `presence_control` 40 | * Paste [presence-control.script](presence-control.script) content into `Source` 41 | * Withing script: 42 | * Modify `subjects` array 43 | * Adjust values of `url` and `http-data` 44 | * Leave other options as-is 45 | * Click `Apply` 46 | * Create new scheduler `System` -> `Schedulers` -> `Add New` 47 | * Tick `Enabled` 48 | * Set `Name` to `presence_control` 49 | * Set `Interval` to `00:00:05` 50 | * Set `On Event` to `presence_control` 51 | * Click `Apply` 52 | -------------------------------------------------------------------------------- /presence-control.script: -------------------------------------------------------------------------------- 1 | :local arriveSendTimes 5 2 | :global subjects {{name="User1";mac="FF:FF:FF:FF:FF:FF";state=0};{name="User2";mac="AA:BB:CC:DD:EE:FF";state=0};{name="User3";mac="DD:DD:DD:DD:DD:DD";state=0}} 3 | 4 | :put "Subjects:" 5 | :foreach entry in=$subjects do={ 6 | :put ($entry) 7 | } 8 | 9 | :local clients [:toarray ""] 10 | :put "Registered WiFi clients:" 11 | :foreach i in=[/interface wireless registration-table find] do={ 12 | :local mac [/interface wireless registration-table get $i value-name=mac-address] 13 | :set $clients ($clients, "$mac") 14 | :put $mac 15 | } 16 | 17 | :put "Checking subject presence..." 18 | 19 | :foreach entry in=$subjects do={ 20 | :local state ($entry->"state") 21 | :local name ($entry->"name") 22 | :foreach mac in=$clients do={ 23 | :if ($mac = $entry->"mac") do={ 24 | :set $state ($state + 1) 25 | :put "$name present" 26 | } 27 | } 28 | if ((($entry->"state") = $state) and ($state != 0)) do={ 29 | :put "$name left" 30 | :set ($entry->"state") 0 31 | :tool fetch mode=http http-method=post http-data="" url="http://homebridge:51828/?sensor=$name&state=false" 32 | } else={ 33 | if ((($entry->"state") != $state) and ($state <= $arriveSendTimes)) do={ 34 | :put "$name arrived" 35 | :set ($entry->"state") $state 36 | :tool fetch mode=http http-method=post http-data="" url="http://homebridge:51828/?sensor=$name&state=true" 37 | } 38 | } 39 | } 40 | --------------------------------------------------------------------------------