MQTT Owntracks HELP!

Hello All,

So basically trying to capture the data received from owntracks via mqtt and have it populate fields such as latitude, longitude, battery, etc…

I am trying to get another users rule working to no avail,

rule "MQTT Owntracks JC"
  when
    Item JCRawData changed
  then
      logInfo("MQTT", "MQTT Owntracks JC data received")
      val String json = (JCRawData.state as StringType).toString
      val String type = transform("JSONPATH", "$._type", json)
      if (type == "location") {
      val String lat  = transform("JSONPATH", "$.lat", json)
      val String lon  = transform("JSONPATH", "$.lon", json)
      val String acc  = transform("JSONPATH", "$.acc", json)
      val String batt = transform("JSONPATH", "$.batt", json)
      logInfo("MQTT", "MQTT Updating values")
      JCLatitude.postUpdate(lat)
      JCLongitude.postUpdate(lon)
      JCLocation.postUpdate(new PointType(lat + "," + lon))
      JCAccuracy.postUpdate(new DecimalType(acc))
      JCBattery.postUpdate(new PercentType(batt))
    }
end

When mqtt posts to JCRawData i get the following

Error during the execution of rule 'MQTT Owntracks JC': Cannot cast org.openhab.core.library.types.DecimalType to org.openhab.core.library.types.StringType

Can anyone help me get this working!!? pleaaasseee! :wink:

Try:

val Number lat  = transform("JSONPATH", "$.lat", json)
val Number lon  = transform("JSONPATH", "$.lon", json)

Already got it all working. Thanks though!

Cheers,
Jay.

What was the solution?

Well i had to line up the fields correctly, String/Location etc… Then my mqtt string was wrong so it wasnt pulling data lol. Then I had to fix the google maps pin issue on ios but all is good now. I can post my configs if anyone needs them…

Jay,

Yes, If you could post your configs that would be very helpful.

But I just did a complete double take looking at your map. I live in Lancaster, thus were neighbors :slight_smile:

If you ever want to meet for a beer or 2 and talk some geek, we can swap some stories on what we have done and got working.

Hey Paul,

Awesome LOL… Sounds good well def have to do that :wink:

Items:

/* mosquitto JC*/
String JCRawData "RawData %s" (persist) { mqtt="<[mosquitto:owntracks/jcid/jay-cell:state:default]" }
Number JCPosition "Position: [%s]" (persist)
Number JCLatitude "Lattitude: [%s]" (persist)
Number JCLongitude "Longitude: [%s]" (persist)
Location JCLocation "Location: [%s]" (persist)
Number JCAccuracy "Accuracy: [%s %%]" (persist)
Number JCBattery "Battery: [%s %%]" (persist)


Rules:

rule "MQTT Owntracks JC"
  when
    Item JCRawData changed
  then
      logInfo("MQTT", "MQTT Owntracks JCRawData data received")
      val String json = (JCRawData.state as StringType).toString
      val String type = transform("JSONPATH", "$._type", json)
      if (type == "location") {
      val String lat  = transform("JSONPATH", "$.lat", json)
      val String lon  = transform("JSONPATH", "$.lon", json)
      val String acc  = transform("JSONPATH", "$.acc", json)
      val String batt = transform("JSONPATH", "$.batt", json)
      logInfo("MQTT", "MQTT Updating values")
      JCLatitude.postUpdate(lat)
      JCLongitude.postUpdate(lon)
      JCLocation.postUpdate(new PointType(lat + "," + lon))
      JCAccuracy.postUpdate(new DecimalType(acc))
      JCBattery.postUpdate(new PercentType(batt))
    }
end

Sitemap:

Frame label="" {
        Text label="Location" {
                        Webview url="http://....../static/map.html" height=9
                        Frame label="Jay's Data"
                        Text item=JCLatitude
                        Text item=JCLongitude
                        Text item=JCAccuracy
                        Text item=JCBattery
                        Frame label="Zach's Data"
                        Text item=ZCLatitude
                        Text item=ZCLongitude
                        Text item=ZCAccuracy
                        Text item=ZCBattery
        }}

custom map.html: (dont forget to get and apply your API key!)

and copy the pins to /static/mapfiles. You can download them buy going into the mapfiles folder and then issuing the following:

wget http://maps.google.com/mapfiles/ms/icons/red-dot.png
wget http://maps.google.com/mapfiles/ms/icons/green-dot.png
wget http://maps.google.com/mapfiles/ms/icons/blue-dot.png

Then replace my “http://…” with your actual openhab fqdn host and port in map.html.

<!DOCTYPE html>
<html>
  <head>    
    <style type="text/css"> 
    <!--
    .Flexible-container {
      position: relative;
      padding-bottom: 0px;
      padding-top   : 0px;
      height        : 345px ;
      overflow: hidden;
    }

    .Flexible-container iframe,   
    .Flexible-container object,  
    .Flexible-container embed {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }
   -->
   </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=MY-API-KEY&v=3.exp&libraries=places,drawing,geometry"></script>

    <script type="text/javascript">
        ////////////////////////////////////////////////////////////////////////
        // Google Maps JavaScript API:
        // https://developers.google.com/maps/documentation/javascript/?hl=de
        // Marker Icons:
        // https://sites.google.com/site/gmapsdevelopment/
        ////////////////////////////////////////////////////////////////////////

        ////////////////////////////////////////////////////////////////////////
        // JQuery
        ////////////////////////////////////////////////////////////////////////

        var map = null;
        //make an empty bounds variable
        var bounds = new google.maps.LatLngBounds();

        // LatLng's we want to show 
        var latlngHome   = new google.maps.LatLng("42.7718", "-78.8346");
        var latlngJay = new google.maps.LatLng("42.7718", "-78.8346"); // initialize to home ...
        var latlngZach  = new google.maps.LatLng("42.7718", "-78.8346"); // initialize to home ...

        var map_options = { center    : latlngHome,
                            zoom      : 10,
                            mapTypeId : google.maps.MapTypeId.ROADMAP };

        $( "#map_canvas" ).ready($(function() {
          var map_canvas = document.getElementById('map_canvas');
          map = new google.maps.Map(map_canvas, map_options)

          var marker = new google.maps.Marker({
                            position  : latlngHome,
                            map       : map,
                            icon      : 'http://........../static/mapfiles/icon10.png',
                            title     : "Home"
                        })

           var circle = new google.maps.Circle({
                        center        : latlngHome,
                        radius        : 1500,
                        map           : map,
                        strokeColor   : '#050505',
                        strokeOpacity : 0.5,
                        strokeWeight  : 2,
                        fillColor     : '#000000',
                        fillOpacity   : 0,
                      }); // end of [Circle]

           bounds.extend(latlngHome);
        }))

        $( document ).ready($(function() {
            // ******************************************************************************
            $.ajax({
              url     : "http://......../rest/items/JCLocation/state/",
              data    : {},
              success : function( data ) {
                  if ( map == null) { return; }
                  if ( data == "Uninitialized") { return; }

                  var coords = data.split(',');
                  var latlngJay = new google.maps.LatLng(coords[0],coords[1]);

                  var marker = new google.maps.Marker({
                    position  : latlngJay,
                    map       : map,
                    icon      : 'http://............../static/mapfiles/green-dot.png',
                    title     : "Jay's Location"
                  }) // end of [Marker]

                  $.ajax({
                    url     : "http://............/rest/items/JCAccuracy/state/",
                    data    : {},
                    success : function( data ) {
                    if ( data == "Uninitialized") { return; }
                      var accuracy = parseInt(data);
                      var circle = new google.maps.Circle({
                        center        : latlngJay,
                        radius        : accuracy,
                        map           : map,
                        strokeColor   : '#00FF00',
                        strokeOpacity : 0.8,
                        strokeWeight  : 2,
                        fillColor     : '#00FF00',
                        fillOpacity   : 0.35,
                      }); // end of [Circle]

                      bounds.extend(latlngJay);
                      map.fitBounds(bounds);

                    } // end of [function]
                  }) // end of [$.ajax]
                } // end of [function]
            }) // end of [$.ajax]
            // ******************************************************************************
            $.ajax({
              url     : "http://.............../rest/items/ZCLocation/state/",
              data    : {},
              success : function( data ) {
                  if ( map == null) { return; }
                  if ( data == "Uninitialized") { return; }

                  var coords = data.split(',');
                  var latlngZach = new google.maps.LatLng(coords[0],coords[1]);

                  var marker = new google.maps.Marker({
                    position  : latlngZach,
                    map       : map,
                    icon      : 'http://............/static/mapfiles/blue-dot.png',
                    title     : "Zach's Location"
                  }) // end of [Marker]

                  $.ajax({
                    url     : "http://.............../rest/items/ZCAccuracy/state/",
                    data    : {},
                    success : function( data ) {
                    if ( data == "Uninitialized") { return; }
                      var accuracy = parseInt(data);
                      var circle = new google.maps.Circle({
                        center        : latlngZach,
                        radius        : accuracy,
                        map           : map,
                        strokeColor   : '#00FF00',
                        strokeOpacity : 0.8,
                        strokeWeight  : 2,
                        fillColor     : '#00FF00',
                        fillOpacity   : 0.35,
                      }); // end of [Circle]

                      bounds.extend(latlngZach);
                      map.fitBounds(bounds);
                    } // end of [function]
                  }) // end of [$.ajax]
                } // end of [function]
            }) // end of [$.ajax]
            // ******************************************************************************
        }))
    </script>
  </head>
  <body>
    <div id="map_canvas" class="Flexible-container" />
  </body>
</html>
1 Like

I have to say that the only above work that i can take credit for is fixing the map pins. Everything else is a community effort and snippets that I dug up from other contributors so please no thanks or anything…TY!

Side note, you need mqtt for this. Mqttitude is different and used for geolocation/geofencing. If you have mqttitude installed you also may have to remove it due to conflicts as it takes over all the mqtt requests and funnels them into geolocation instead.

thanks for posting,
Where is this calculated / derived from?

Also, which Google API service did you subscribe to / get the API key for?

Visit the APIs Console at https://code.google.com/apis/console and log in with your Google Account.Click the Services link from the left-hand menu.Activate the Google Maps API v3 service.Click the API Access link from the left-hand menu. Your API key is available from the API Access page, in the Simple API Access section.
Maps API applications use the Key for browser apps.

1 Like

I was going to use that for my “Jay is Home”, “Jay is at work” blahblah but i forgot it was there and created JCStatus instead lol so omit that. Thats part of my mqtt geofencing setup…

Heres my rule for that…

rule "OwnTracks Waypoint Update for Jay"
  when
    Item JCWayPointData received update
  then
    logInfo("MQTT", "OwnTracks waypoint updated for Jay")
    sendMail("me@here.com", "MQTT: Device Update (Jay)", "Waypoint update for Jay")
    val String json = (JCWayPointData.state as StringType).toString
    val String myType = transform("JSONPATH", "$._type", json)
    if (myType == "waypoint") {
    val String myDesc = transform("JSONPATH", "$.desc", json)
    JCStatus.postUpdate(myDesc)
    logInfo("OwnTracks", "Jay is at " + myDesc)
    sendMail("me@here.com", "MQTT: Device Update (Jay)", "Jay is at " + myDesc)
    }
end

and item…

String JCWayPointData "WayPoint Data %s" (persist) { mqtt="<[mosquitto:owntracks/jcid/jay-cell/waypoint:state:default]" }

I have waypoints for Home and Work and my son has them for Home, Work, School etc… Once you have these posting you can drive your lights or garage door or whatever with them. When mine changed to “Home” my garage door opens… :wink: You can fine tune the radius in the app and you want to be in “significant change mode” which is the single triangle that looks like a play button. The cool thing about owntracks is it maps and tracks all your family members or devices because they are all subscribed to the same mqtt broker… pretty neat…

22 meters is enough coverage from the house to the end of the driveway so when im on the street it dont open my garage but as soon as i enter the driveway it does :wink:

My son “ZC” was automatically pushed to my app by the broker… I never added him or anything lol neat :wink:

It will show their photos from contacts also if their in there. :wink:

1 Like

Thank you very much for sharing/posting; I am sure there quite few (in hiding) adopting this solution.

No problem,

I will be posting a new rule for geofencing as the current one displays “Home” no matter if i enter or leave a waypoint because its using the description. Stay tuned for that…

here is a working rule for when you enter or leave your home… I’m sure I will customize it a million more times lol

rule "OwnTracks Waypoint Jay"
  when
    Item JCWayPointData received update
  then
    logInfo("MQTT", "OwnTracks waypoint update for Jay")
    sendMail("jay@cidcomm.com", "MQTT: WayPoint update Received (JC)", "Waypoint update for JC Received")
    val String json = (JCWayPointData.state as StringType).toString
    val String myType = transform("JSONPATH", "$._type", json)
    val String myEvent = transform("JSONPATH", "$.event", json)
    val String myDesc = transform("JSONPATH", "$.desc", json)
    if (myType == "transition" && myEvent == "enter" && myDesc == "Home") {
    JCStatus.postUpdate("Home")
    logInfo("Transition", "Jay has arrived at " + myDesc)
    sendMail("jay@cidcomm.com", "Transition: WayPoint update Applied (JC)", "Jay has arrived at " + myDesc)
    }
    if (myType == "transition" && myEvent == "leave" && myDesc == "Home") {
    JCStatus.postUpdate("Traveling")
    logInfo("Transition", "Jay has left " + myDesc)
    sendMail("jay@cidcomm.com", "Transition: WayPoint update Applied (JC)", "Jay has left " + myDesc)
    }
end

Here is a better rule that covers home/geofencing AND any extra waypoints you have in owntracks…

rule "OwnTracks Waypoint Jay"
  when
    Item JCWayPointData received update
  then
    logInfo("MQTT", "OwnTracks waypoint update for Jay")
    sendMail("jay@cidcomm.com", "MQTT: WayPoint update Received (JC)", "Waypoint update for JC Received")
    val String json = (JCWayPointData.state as StringType).toString
    val String myType = transform("JSONPATH", "$._type", json)
    val String myEvent = transform("JSONPATH", "$.event", json)
    val String myDesc = transform("JSONPATH", "$.desc", json)
    if (myType == "transition" && myEvent == "enter" && myDesc == "Home") {
    JCStatus.postUpdate("Home")
    logInfo("Transition", "Jay has arrived at " + myDesc)
    sendMail("jay@cidcomm.com", "Transition: WayPoint update Applied (JC)", "Jay has arrived at " + myDesc)
    }
    if (myType == "transition" && myEvent == "leave" && myDesc == "Home") {
    JCStatus.postUpdate("Traveling")
    logInfo("Transition", "Jay has left " + myDesc)
    sendMail("jay@cidcomm.com", "Transition: WayPoint update Applied (JC)", "Jay has left " + myDesc)
    }
    if (myType == "transition" && myEvent == "enter" && myDesc != "Home") {
    JCStatus.postUpdate(myDesc)
    logInfo("Transition", "Jay has arrived at " + myDesc)
    sendMail("jay@cidcomm.com", "Transition: WayPoint update Applied (JC)", "Jay has arrived at " + myDesc)
    }
    if (myType == "transition" && myEvent == "leave" && myDesc != "Home") {
    JCStatus.postUpdate(myDesc)
    logInfo("Transition", "Jay has left " + myDesc)
    sendMail("jay@cidcomm.com", "Transition: WayPoint update Applied (JC)", "Jay has left " + myDesc)
    }


end

For visbility my item for this is: and again i recommend removing “mqttitude” because it will cause problems with mqtt as it takes over and traps all “mqtt” and “mqttitude” messages and will render all this useless…

String JCWayPointData "JCWayPointData %s" (persist) { mqtt="<[mosquitto:owntracks/jcid/jay-cell/event:state:default]" }
1 Like

new rule. This one focuses on entering your waypoints such as “Home” to turn things on or off and any other waypoints you have listed in the app. Anything else should result in “Traveling” being displayed. So you are “Home”, at “Work”, at “School” or catchall “Traveling”

rule "OwnTracks Waypoint Jay"
  when
    Item JCWayPointData received update
  then
    logInfo("MQTT", "OwnTracks waypoint update for Jay")
    sendMail("jay@cidcomm.com", "MQTT: WayPoint update Received (JC)", "Waypoint update for JC Received")
    val String json = (JCWayPointData.state as StringType).toString
    val String myType = transform("JSONPATH", "$._type", json)
    val String myEvent = transform("JSONPATH", "$.event", json)
    val String myDesc = transform("JSONPATH", "$.desc", json)
    if (myType == "transition" && myEvent == "enter" && myDesc == "Home") {
    JCStatus.postUpdate("Home")
    logInfo("Transition", "Jay has arrived at " + myDesc)
    sendMail("jay@cidcomm.com", "Transition: WayPoint update Applied (JC)", "Jay has arrived at " + myDesc)
    }
    if (myType == "transition" && myEvent == "enter" && myDesc != "Home") {
    JCStatus.postUpdate(myDesc)
    logInfo("Transition", "Jay has arrived at " + myDesc)
    sendMail("jay@cidcomm.com", "Transition: WayPoint update Applied (JC)", "Jay has arrived at " + myDesc)
    }else{
    JCStatus.postUpdate("Traveling")
    logInfo("Transition", "Jay has left " + myDesc)
    sendMail("jay@cidcomm.com", "Transition: WayPoint update Applied (JC)", "Jay has left " + myDesc)
}

end

Same as last one but way simpler…

rule "OwnTracks Waypoint Jay"
  when
    Item JCWayPointData received update
  then
    logInfo("MQTT", "OwnTracks waypoint update for Jay")
    sendMail("jay@cidcomm.com", "MQTT: WayPoint update Received (JC)", "Waypoint update for JC Received")
    val String json = (JCWayPointData.state as StringType).toString
    val String myType = transform("JSONPATH", "$._type", json)
    val String myEvent = transform("JSONPATH", "$.event", json)
    val String myDesc = transform("JSONPATH", "$.desc", json)
    if (myType == "transition" && myEvent == "enter") {
    JCStatus.postUpdate(myDesc)
    logInfo("Transition", "Jay has arrived at " + myDesc)
    sendMail("jay@cidcomm.com", "Transition: WayPoint update Applied (JC)", "Jay has arrived at " + myDesc)
    }
    if (myType == "transition" && myEvent == "leave") {
    JCStatus.postUpdate("Traveling")
    logInfo("Transition", "Jay has left " + myDesc)
    sendMail("jay@cidcomm.com", "Transition: WayPoint update Applied (JC)", "Jay has left " + myDesc)
    }

end
1 Like