Dockerized OH iPhone Detection with HPING3 and sensorReporter

presence
iphone
Tags: #<Tag:0x00007f21274c1c70> #<Tag:0x00007f21274c1b30>

(Rich Koshak) #1

Groan, not another iPhone presence detection tutorial.

OK, here is the deal for why I wrote this.

  1. I run OH in a docker container and I do not want to run it as root. Therefore I cannot use the dhcplisten nor the new arpping features of the Network binding.

  2. I run in an unmodified docker container so access to commands like hping3 are not available to the Exec binding.

  3. I’d rather use a solution that doesn’t depend on a script running on the router at this time.

  4. This was a quicker and easier way to use than interacting with the icloud interface discussed here. Plus I only care about whether the device is home, my wife would find it creepy if I were to track her location everywhere.

Because of 1 and 2, I need a way to execute things I would normally run using the Exec binding some other way. I already have my sensorReporter script running on three Raspberry Pis and counting and this script already communicates using MQTT and I’ve already written a module for it to execute command line scripts. So the following approach was a no-brainer.

This posting does not go into detail about how to install and use sensorReporter. Ask questions below if you run into trouble.

This posting also assumes your router or phone has been configured with a static IP.

Approach

Configure sensorReporter with an execActuator config that executes the script by @rtvb in this posting. I made one modification to include ${IP} in the echo of the result (i.e. replace echo "OFF" with echo "${IP} OFF" and the same for echo ON). So, for example, if the IP passed in a 192.168.1.100 then the script will output 192.168.1.100 ON. More on why in a moment.

Then configure a String Item in OH to send the IP address and MAC you want to ping as an MQTT message. Configure another Switch Item to subscribe for the results for that IP. You need only the one outgoing Item but a separate incoming Switch for each device you care about.

sensorReporter

To configure the exeActuator use a config like below.

[Actuator1]
Class: execActuator.execActuator
Type: Exec
Connection: MQTT
Poll: 0
Command: ./iphoned.sh
CMDTopic: scripts/presence/iphone/cmd
ResultTopic: scripts/presence/iphone/results

Use your own CMD and Result topics and the above assumes the iphoned.sh script discussed above is in the same folder sensorReporter is run from. Provide a full path if it is located somewhere else.

Note that sensorReporter needs to either run as root or you need to add a sudo to the Command and add what ever user sensorReporter is running as to sudoers so it doesn’t need a password to run this script.

openHAB

Below uses the presence detection example documented here.

Items:

String aHping3 "Ask sensorReporter to hping3 and arp ping device [%s]"
  <present> (gPresent)
  { mqtt=">[mosquitto:scripts/presence/iphone/cmd:command:*:default]" }

Switch viPhone_Net "iPhone Presence"
  <present> (gPresent)
  { mqtt="<[mosquitto:scripts/presence/iphone/results:command:REGEX(192.168.1.100 (.*)):192.168.1.100 .*]" }

NOTE: the aHping3 Item could be done away with and replaced with a call using the MQTT Action. I had problems with the Action a long time ago and never had a chance to reinstall it.

The magic happens in the transform and matching regex of the second Item. The transform will extract the ON or OFF from the message that starts with the IP address we care about. The filter regex causes the binding to only try to transform those messages that start with the IP address we care about which avoids errors in the logs and the Switch from going crazy with messages for other IP addresses.

If you have more than one device, create more Switch Items and change the two regular expressions to match those other device’s IPs.

Rules:

rule "Ask sensorReporter to hping Jenn's iPhone"
when
	Time cron "0 * * * * ? *" 
then
	aHping3.sendCommand("192.168.1.103 68:db:ca:a4:4c:98")
end

In this case, we are sending the IP address and MAC which gets passed to iphoned.sh. If you have more than one iPhone or other device type you want to hping3 detect you need to send that IP/MAC pair as separate commands.

There are tons of other ways to issue the command to poll for the device but this way was convenient.

I hope this provides some inspiration for those running OH in a Docker or are otherwise constrained to have OH do network operations or use the Exec binding.


(Rhyssman) #2

Hi @rlkoshak

I am trying to follow your guide to setup sensorReporter.

I cannot start the sensorReporter service with the following logged errors from systemd

Oct 26 15:28:09 rpi3 sensorReporter.py[9300]:   File "/opt/sensorReporter/sensorReporter.py", line 71, in main
Oct 26 15:28:09 rpi3 sensorReporter.py[9300]:     loadConfig(sys.argv[1])
Oct 26 15:28:09 rpi3 sensorReporter.py[9300]:   File "/opt/sensorReporter/sensorReporter.py", line 217, in loadConfig
Oct 26 15:28:09 rpi3 sensorReporter.py[9300]:     createConnection(config, section)
Oct 26 15:28:09 rpi3 sensorReporter.py[9300]:   File "/opt/sensorReporter/sensorReporter.py", line 188, in createConnection
Oct 26 15:28:09 rpi3 sensorReporter.py[9300]:     logger.error("%s.%s is not supported on this platform" % module_name, class_name)
Oct 26 15:28:09 rpi3 sensorReporter.py[9300]: TypeError: not enough arguments for format string

mqttReporter.log dump

2018-10-26 15:28:09,864 INFO - ---------------Started
2018-10-26 15:28:09,865 INFO - Creating connections...
2018-10-26 15:28:09,866 INFO - Creating connection MQTT

That tells me the code is breaking on one of the following lines:

sensorReporter.py

183      module_name, class_name = config.get(section, "Class").rsplit(".", 1)
184     MyConn = getattr(importlib.import_module(module_name), class_name)
185      params = lambda key: config.get(section, key)
186     connections[name] = MyConn(on_message, logger, params, sensors, actuators)

So its failing to make a connection to my MQTT broker. I double checked the ini file and seems fine.

Any ideas

Regards

Rhyss


(Rich Koshak) #3

Show the mqtt section of the in file. For some reason it is not parsing it correctly. The error is almost certainly there. Obviously obfuscate usernames and passwords.


(Rhyssman) #4

Straight out of default.ini

sensorReporter.ini

[Connection1]
Class = mqttConn.mqttConnection
Name = MQTT
User = "removed"
Password = "removed"
Host = localhost
Port = 1883
Keepalive = 60
; Topic to listen on, when any message is received, the current state of all
; are published to their respective topics.
Topic = sensors/getUpdate
; The MQTT broker will publish the following message on the following topic
; when the client disconnects (cleanly or crashes)
LWT-Topic = status/sensor-reporters
LWT-Msg = mqttReporter is dead
; If TLS is yes the connection will be encrypted, the Certificate is expected to be in
; ./certs/ca.crt"
TLS = NO

(Rich Koshak) #5

You don’t have paho-mqtt installed. As described in the readme

MQTT depends on the Paho library.

The install.sh in the config folder lists all the commands necessary to install dependencies…

So make sure to install paho-mqtt and any other dependency you have depending on which extension you are using.


(Rhyssman) #6

Hi Richard

Got it. I didnt realise that python installs were per user. As I am running sensorReporter as root I needed to run pip install as sudo

sudo pip install paho-mqtt subprocess32

Also suggest adding the following to default.ini

[Sensor8]
Num-Dest = status/heartbeat/num
Str-Dest = status/heartbeat/str
; Destination = status/heartbeat

[Connection1]
client = sensorReporter

Thanks for your help