A generic pimatic plugin for mobile devices
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
assets
screenshots
test
.gitignore
.travis.yml
CookBook.md
Gruntfile.coffee
LICENSE
README.md
actions.coffee
device-config-schema.coffee
iframe_percentage_width.patch
package.json
phone-config-schema.coffee
phone.coffee

README.md

Build Status Version downloads

pimatic-phone

Step-by-step instructions to setup a phone device with Google iFrame mapping, geocoding and iCloud update control as outlined in the above screenshot are available in a separate Cookbook

A generic pimatic plugin for mobile devices to provide location based devices. Continuous GPS tracking and reverse geocoding are expensive in terms of mobile power consumption and Google/OSM API requests. Many location based rules will work well with known locations like "Home" or "Office". The plugin was inspired by the pimatic-locatin-plugin but uses a different device layout and (as of Rev. 0.6.0) a session based iCloud client from icloud-promise for iOS devices.

The signature of the updateLocation API call provides compatibility with the Android App PimaticLocation.

From revision Rev. 0.9.0 reverse Geocoding for the also supported. The new address attribute could be maintained manually through the plugin location map configuration or by reverse Geocoding by the Google Maps Geocoding API.

Make sure, your Google API key is at least activated for the Google Maps Embed API and the Google Maps Geocoding API.

With revision Rev. 0.8.0 an iframeDevice from pimatic-iframe can be utilized to show the current location on a map. Default settings use the Google Maps Embed API. You have to register a project at the Google Developer Console and generate an API key.

iOS devices

  • Notification emails: A notification email from Apple is generated when the iCloud session is established on pimatic startup/device creation.

  • Update interval (I): Requesting location information from the iPhone triggers the device to push the data to the iCloud. A short period increases power consumption significantly and may drain your battery.

  • Update interval (II): Use rules and the pimatic-phone API to suspend location updates, e.g. if the device is connected to WiFi at home: Use pimatic-ping or pimatic-cron to trigger the suspend by executing (inspired by a request at the pimatic forum). This feature could not be used if you have two factor authentication activated. See 2FA remarks (see below). As of Rev. 0.8.0 you can define a DummySwitch to enable/disable iCloud updates through the mobile frontend and since Rev. 0.8.5 you can use the new actions "suspend <phone device>" and "resume <phone device>" to control updates through the iCloud interface. See Device Actions for details.

    curl --user "admin:admin" --silent --request GET \
    http://localhost:8080/api/device/<IPHONE>/suspend?flag=true
  • Session ID and cookies are not permanently stored but recreated at pimatic startup/iOS device initialisation. Their is no automatic reconnect of sessions to avoid flooding with notification mails due to configuration issues or other problems. In case of an error and a lost connection open the configuration dialog of the device. A new session is established when you recreate the device by clicking the save button. Their is no need to restart pimatic.

  • Two factor authentication (2FA): If activated, a notification dialog pops up on your device requiring a confirmation for the session. Also a verification code is displayed. It seems that neither the confirmation nor the verification code is really necessary to access the iCloud device information. You can avoid this messages by generating a verification code on your iPhone (Settings -> iCloud -> Apple ID -> Security -> Verification Code) and use this code in the iCloudVerify configuration option. Currently their is no possibility to refresh 2FA sessions. Keep your iCloudInterval lesser then the session timeout of 600 seconds. As of Rev. 0.7.6 additional API calls (enable/disableUpdates, see API documentation below) may be used to suspend updates for 2FA sessions. Due to limitations of the iCloud API logout and login calls have to be performed and Apple notification mails are triggered by the enableUpdates call. You have to provide a valid verification code or '000000' as in https://.../enableUpdates?code=000000.

    As of Rev. 0.8.5 you can use the new actions "suspend" and "resume" to control the iCloud updates. The resume action takes an additional argument "with " if 2FA is enabled. Combined with rules, a buttons device und a variable input device you can realize a comfortable frontend to control suspend/resume with verification codes.

Android devices

As of Rev. 0.4.6 an additional API call updatePhone provides a simple to use interface for Android devices running the Tasker APP. Download and import the sample project to Tasker and change the server settings in the HTTP Get task. See the Tasker Setup Guide for details.

Location Map

The location map (maintained in the plugin settings) allows you to define well known location tags and let you use the most suitable method (native apps, tasker jobs, GPS/GSM tracking, WLAN connections, etc.) to update the location of a mobile device.

Since Rev. 0.4.2 overlapping locations are supported. You can, for example, define a location "Home" with latitude=55.60, longitude=10.80 and radius=250m and a location "NearHome" with the same gps data but a radius of 1000m. A distance of 200m will provide the location "Home", 500m give you "NearHome".

Location tags are similar to geofences and client apps like Locative for iOS or Android can be used to update the device location with the new GET requests enter and exit. See API documentation below for details.

With revision 0.7.5 all API calls return the current device location on success.

{
  "result":
  {
    "tag":"Home",
    "source":"TAG",
    "type":"API",
    "time":"2017-02-02 15:47:05",
    "utc":1486046825540,    
    "gps":
    {
      "latitude":53.12345678,
      "longitude":10.87654321
    }
  },
  "success":true
}

Also two additional api calls fetchLocation and fetchPreviousLocation are implemented to provide the location information by simple GET requests. See the API documentation below for details.

Location based rules

No additional predicates or rule actions are provided in the moment but you can use dynamically generated device variables and attributes, e.g.

when $phone.location gets updated and $phone.tag != "Home" then turn lights off
when location of phone is equal to "Office" then log "at work"
when $phone.distanceToHome is lower than 500 then log "almost at home"
...

Device Actions

Suspend/resume iCloud updates for iOS devices

WHEN [button pressed] THEN suspend <iOSDevice>
WHEN [button pressed] THEN resume <iOSDevice> [with "<verify>"]

where "verify" is the next valid verification code for 2FA

Simulate device movement

WHEN [button pressed] THEN set location of <phone> to "address"

where "address" is one of your location tags or any valid expression for a Google Maps Geocoding API lookup

Device Predicates (planned)

In addition to device attributes predicates native predicates should improve and simplify location based rules, as in

WHEN distance to <location> is less than 500 meter THEN ...
WHEN route to <location> by car is less than 500 meter THEN ...
WHEN eta to <location> on food is less than 5 minutes THEN ...

Predicates will be available with the next milestone release 1.0.0

Use xLinks to open maps for device location (deprecated)

As of Rev. 0.4.0 you can define URL templates to open Google Maps or Open Street Map for the current device location:

      xLinkTemplate:
        description: "URL template"
        type: "string"
        default: "https://www.google.com/maps?q={latitude}+{longitude}"

Limitations: The values are not updated in the frontend. You have to manually refresh the browser window. Due to this linḿitations, the xLink feature will be removed. Use the pimatic-iframe based approach available since Rev. 0.8.0.

Plugin configuration

Provides a location table to map geo locations (GPS), mobile cell tower positions (GSM) and WiFi connections (SSID) to user defined location tags

  "plugins": [
    {
      "locations": [
        {
          "name": "office",
          "tag": "Office",
          "ssids": [
            "DIGITEC"
          ],
          "gps": {
            "latitude": 53.5544809,
            "longitude": 9.9786172,
            "radius": 250
          },
          "cids": [
            "GSM:42407.5455365",
            "GSM:1401.43266861",
            "GSM:42407.5455361"
          ]
        },
        {
          "name": "home",
          "tag": "Home",
          "ssids": [
            "AVM",
            "ASUS"
          ],
          "gps": {
            "latitude": 53.66,
            "longitude": 10.08,
            "radius": 250
          },
          "cids": [
            "GSM:42441.5453313",
            "GSM:1401.43266781",
            "GSM:411.13021"
          ]
        }
      ],
      "plugin": "phone",
      "active": true,
      "debug": true
    }
  ],

Devices

Device specific configuration

PhoneDevice: Generic mobile device, updates it's location via API calls (Tasker scripts, Apps)

    {
      "serial": "HTC0815",
      "xAttributeOptions": [],
      "id": "phone_htc-m9",
      "name": "ViperOneM9",
      "class": "PhoneDevice"
    }

PhoneDeviceIOS: Apple mobile devices, uses icloud-promise API to update the location periodically

    {
      "iCloudUser": "user@domain",
      "iCloudPass": "password",
      "iCloudDevice": "Users iPhone",
      "xAttributeOptions": [],
      "id": "phone_user",
      "name": "Users iPad",
      "class": "PhoneDeviceIOS",
      "debug": true,
      "accuracy": 500
    }

Device configuration option details

  PhoneDevice:
    title: "Phone device config"
    type: "object"
    extensions: ["xAttributeOptions", "xLink"]
    properties:
      serial:
        description: "Serial number of device"
        type: "string"
        default: ""
      debug:
        description: "Enable debug output"
        type: "boolean"
        default: false
      accuracy:
        description: "Radius (m) for GPS mapping"
        type: "number"
        default: 250
      gpsLimit:
        description: "Log new position only if significantly moved"
        type: "number"
        default: 250
      googleMaps:
        description: "Optional Google Maps API options"
        type: "object"
        default: {}
        properties:
          key:
            description: "Optional Google API key to be used in the iFrame URL"
            type: "string"
            default: ""
          geocoding:
            description: "Lookup location for address"
            type: "boolean"
            default: true
          reverseGeocoding:
            description: "Lookup address for location"
            type: "boolean"
            default: true
      iFrame:
        description: "iFrame configuration"
        type: "object"
        default: {}
        properties:
          id:
            description: "iFrame device id"
            type: "string"
            default: ""
          url:
            description: "iFrame URL template"
            type: "string"
            default: "https://www.google.com/maps/embed/v1/place?key={key}&q={address}"
          enabled:
            description: "Enable iFrame updates"
            type: "boolean"
            default: false
          switch:
            description: "Optional enable switch device id"
            type: "string"
            default: ""
      xLinkTemplate:
        description: "URL template"
        type: "string"
        default: "https://www.google.com/maps?q={latitude}+{longitude}"

  PhoneDeviceIOS:
    title: "iPhone device configuration"
    type: "object"
    extensions: ["xAttributeOptions", "xLink"]
    properties:
      iCloudUser:
        description: "iCloud user (Apple ID)"
        type: "string"
        default: ""
      iCloudPass:
        description: "iCloud password"
        type: "string"
        default: ""
      iCloud2FA:
        description: "iCloud 2FA"
        type: "boolean"
        default: false
      iCloudVerify:
        description: "iCloud 2FA verification code"
        type: "string"
        default: "000000"
      iCloudVerifyVariable:
        description: "Name of the $variable providing the code"
        type: "string"
        default: ""
      iCloudDevice:
        description: "iCloud device name"
        type: "string"
        default: ""
      iCloudInterval:
        description: "iCloud poll interval (seconds)"
        type: "integer"
        default: 300
      iCloudSessionTimeout:
        description: "iCloud session expiration timeout"
        type: "integer"
        default: 600
      iCloudSuspended:
        description: "iCloud updates suspended"
        type: "boolean"
        default: false
      iCloudSwitch:
        description: "iCloud suspend switch device id"
        type: "string"
        default: ""
      iCloudTimezone:
        description: "iCloud client timezone"
        type: "string"
        default: "Europe/Berlin"
      debug:
        description: "Enable debug output"
        type: "boolean"
        default: false
      accuracy:
        description: "Radius (m) for GPS mapping"
        type: "number"
        default: 250
      gpsLimit:
        description: "Log new position only if significantly moved"
        type: "number"
        default: 250
      googleMaps:
        description: "Optional Google Maps API options"
        type: "object"
        default: {}
        properties:
          key:
            description: "Optional Google API key to be used in the iFrame URL"
            type: "string"
            default: ""
          geocoding:
            description: "Lookup location for address"
            type: "boolean"
            default: true
          reverseGeocoding:
            description: "Lookup address for location"
            type: "boolean"
            default: true
      iFrame:
        description: "iFrame configuration"
        type: "object"
        default: {}
        properties:
          id:
            description: "iFrame device id"
            type: "string"
            default: ""
          url:
            description: "iFrame URL template"
            type: "string"
            default: "https://www.google.com/maps/embed/v1/place?key={key}&q={address}"
          enabled:
            description: "Enable iFrame updates"
            type: "boolean"
            default: false
          switch:
            description: "Optional enable switch device id"
            type: "string"
            default: ""
      xLinkTemplate:
        description: "URL template"
        type: "string"
        default: "https://www.google.com/maps?q={latitude}+{longitude}"

Attributes

The following attributes are available and can be used in rules, for logging or may be displayed in the frontend. Another set of attributes named distanceTo<Tag> is created dynamically and updated by location changes.

    attributes:
      timeSpec:
        label: "Update time spec"
        description: "Date and time of the last location update."
        type: t.string
        unit: ""
        acronym: 'DT'
        displaySparkline: false
        hidden: false
        discrete: true
      timeStamp:
        label: "Update time stamp"
        description: "Date and time of the last location update."
        type: t.number
        unit: ""
        acronym: 'UTC'
        displaySparkline: false
        hidden: true
        discrete: true
      tag:
        description: "Current location of the device"
        type: t.string
        unit: ""
        acronym: 'LOC'
        displaySparkline: false
        hidden: false
        discrete: true
      location:
        description: "Alias for the tag attribute"
        type: t.string
        unit: ""
        acronym: 'LOC'
        displaySparkline: false
        hidden: true
        discrete: true
      position:
        description: "Alias for the tag attribute"
        type: t.string
        unit: ""
        acronym: 'LOC'
        displaySparkline: false
        hidden: true
        discrete: true
      previousTag:
        description: "Previous location of the device"
        type: t.string
        unit: ""
        acronym: 'PREV'
        displaySparkline: false
        hidden: true
        discrete: true
      previousLocation:
        description: "Alias for the previous tag attribute"
        type: t.string
        unit: ""
        acronym: 'PREV'
        displaySparkline: false
        hidden: true
        discrete: true
      previousPosition:
        description: "Alias for the previous tag attribute"
        type: t.string
        unit: ""
        acronym: 'PREV'
        displaySparkline: false
        hidden: true
        discrete: true
      source:
        label: "Location source"
        description: "Source of location information: LOC, GPS, NET, TAG, SSID, ..."
        type: t.string
        unit: ""
        acronym: 'SRC'
        displaySparkline: false
        hidden: false
        discrete: true
      type:
        label: "Type"
        description: "Type of position data"
        type: t.string
        unit: ""
        acronym: 'TYP'
        displaySparkline: false
        hidden: false
      latitude:
        label: "Latitude"
        description: "Latitude of device"
        type: t.number
        unit: "°"
        acronym: 'LAT'
        displaySparkline: false
        hidden: false
      longitude:
        label: "Longitude"
        description: "Longitude of device"
        type: t.number
        unit: "°"
        acronym: 'LONG'
        displaySparkline: false
        hidden: false
      accuracy:
        label: "Accuracy"
        description: "Accuracy of location data"
        type: t.number
        unit: "m"
        acronym: 'ACC'
        displaySparkline: false
        hidden: true
      cell:
        label: "Cell"
        description: "Cell ID"
        type: t.string
        unit: ""
        acronym: 'CELL'
        displaySparkline: false
        hidden: true
      ssid:
        label: "SSID"
        description: "WLAN SSID"
        type: t.string
        unit: ""
        acronym: 'SSID'
        displaySparkline: false
        hidden: true
      gps:
        label: "GPS"
        description: "GPS"
        type: t.string
        unit: ""
        acronym: 'GPS'
        displaySparkline: false
        hidden: true
      address:
        label: "Address"
        description: "Address of device"
        type: t.string
        unit: ""
        acronym: 'ADDR'
        displaySparkline: false
        hidden: false

Many of the attributes are volatile in nature. Adjust database logging options according to your needs, e.g.:

    "database": {
      "deviceAttributeLogging": [
        # ...
        {
          "deviceId": "phone_*",
          "attributeName": "*",
          "type": "*",
          "interval": "0",
          "expire": "0"
        },
        {
          "deviceId": "phone_*",
          "attributeName": "tag",
          "expire": "1y"
        },
        {
          "deviceId": "phone_*",
          "attributeName": "gps",
          "expire": "1y"
        }
      ],
      #...
    }

With Rev. 0.4.1 a new configuration option gpsLimit allows you to restrict the logging: Updates are only written to the database when the location tag changes or a significant movement > gpsLimit was detected between two updates.

Device actions

Different actions/API calls can be used to update the device location. Use HTTP(S) GET requests like

http(s)://<host>/api/device/<deviceId>/<action>?<key>=<value>[&<key>=<value]...

where is the domain name/address of your pimatic instance, is the deviceId of your mobile and call is one of the following:

call key(s) value comment
updateTag tag location tag set the location tag directly
enter tag location tag set the location tag from geofence app
exit tag location tag set the location tag from geofence app
updateGPS latitude,longitude,accuracy,source gps data used internally for iCloud devices
updateCID cid %CELLID Android tasker mobile cell ID
updateSSID ssid ssid SSID of connected WLAN
updateLocation long,lat,updateAddress gps data legacy call for PimaticLocation Android App
updatePhone serial,ssid,ssid,... Tasker vasrs see documentation for details
fetchLocation n/a n/a return current device location
fetchPreviousLocation n/a n/a return the previous location
updateDeviceConfig n/a n/a check and update location settings
suspend flag true/false, on/off suspend location updates, iOS devices only!
disableUpdates n/a n/a logout and disable updates for iOS devices with 2FA
enableUpdates code (verification) 000000 login and enable updates for iOS devices with 2FA

Example:

    curl --user "admin:admin" --silent --request GET \
    http://localhost:8080/api/device/<IPHONE>/enter?tag=Home

Available API call os of Rev. 0.9.5

      update:
        description: "Variable update record"
        params:
          record:
            type: t.string
      updatePhone:
        description: "Update from Android Tasker APP"
        params:
          serial:
            type: t.string
          ssid:
            type: t.string
          cellid:
            type: t.string
          locn:
            type: t.string
          loc:
            type: t.string
      updateTag:
        description: "Update location tag of device"
        params:
          tag:
            type: t.string
      updateAddress:
        description: "Update address of device"
        params:
          address:
            type: t.string
      enter:
        description: "Enter geofence"
        params:
          tag:
            type: t.string
      exit:
        description: "Exit geofence"
        params:
          tag:
            type: t.string
      updateGPS:
        description: "Update geo location values"
        params:
          latitude:
            type: t.number
          longitude:
            type: t.number
          accuracy:
            type: t.number
          source:
            type: t.string
      updateCID:
        description: "Update mobile cell id"
        params:
          cell: t.string
      updateSSID:
        description: "Update location from WLAN connection"
        params:
          ssid: t.string
      updateLocation:
        description: "Legacy: pimatic-location Android app"
        params:
          long:
            type: t.number
          lat:
            type: t.number
          updateAddress:
            type: t.number
      fetchLocation:
        description: "Return current device location"
      fetchPreviousLocation:
        description: "Return previous device location"
      updatePluginConfig:
        description: "Update location settings via geocoding lookups"

TODO: detailed description of calls and params, curl examples, tasker examples

Roadmap

  • Generate HTML links to display device location in Google Maps
  • Generate HTML links to display device location in Open Street Map
  • Display current location in maps iframe (Google/OSM)
  • Add distance attribute (distance between geo locations)
  • Provide device predicates: location, distance, eta, ...
  • Use Google Maps for route calculations

Changelog

v0.9.6

  • bugfix alias attribute updates [#3]

v0.9.5

  • bugfix GPS validation

v0.9.4

  • fixed files in package.json

v0.9.3

  • fixed gpsLimit bug for Android devices

v0.9.2

  • public release
  • new device action updatePluginConfig

v0.9.1

  • use (reverse) geocoding from Googlke Maps API make sure, your api key is activated for Embed and Geocoding API
  • addtional attribute "address" (from config or reverseGeocoding)
  • addtitional action updateAddress for reverse geocoding
  • plugin an device configuratin changes (ignore warnings thrown on first startup with new plugin configuration

v0.8.5

  • iOS device config changes iCloudVerifyVariable to use with VariableInputDevice iCloud2FA used during startup before a iCloud connection is availabel

  • provide first pimatic actions "set location" and "suspend/resume"

v0.8.4

  • more diagnostic output if device specific debug is enabled

v0.8.3

  • suspend attribute refactoring

v0.8.2

  • bugfix device recreation error

v0.8.0

  • use pimatic-iframe for device location
  • use DummySwitch for iCloud update suspend

v0.7.7

  • bugfix device initialization from lastState

v0.7.6

  • iCloudSuspended configuration attribute
  • disable/enableUpdates API calls for 2FA sessions

v0.7.5

  • API calls return JSON response
  • support for previousLocation attributes
  • additional API calls: enter, exit, fetchLocation, fetchPreviousLocation

v0.7.3

  • force UI update on recreation of device
  • additional device debugging output if enabled
  • minor bugfixes

v0.7.2

  • use refreshClient during initalization

v0.7.1

  • validate device location (may be undefined) if location service is disabled

v0.7.0

  • enhanced configuration options for iOS devices
  • use icloud-promise module
  • suspend iCloud location updates via AOI call

v0.6.3

  • updated documentation

v0.6.1

  • iOS support with session based iCloud client module

v0.5.0

  • preliminary hot fix iOS device support

[Support for iOS devices broken due to iCloud API changes!]

v0.4.6

  • updatePhone API call for Android Tasker APP

v0.4.5

  • initial grunt/mocha setup and travis integration

v0.4.4

  • update location only on relevant changes
  • significant movements > gpsLimit (v0.4.1)
  • tag, source or type changes through API calls (new)

v0.4.3

  • tag initialization on startup [#1]

v0.4.2

  • support for overlapping locations

v0.4.1

  • update location only on significant movements > gpsLimit

v0.4.0

  • xLink to location URL

v0.3.1

  • Stable release with dynamic distance attributes