Page 1 of 7

Traffic with Google Maps in Domoticz

Posted: Thursday 07 April 2016 9:57
by woody4165
Hi

just found that I can check the traffic with Google Maps.
I tried out the fantastic script with Waze, but don't know why, in my case, the result I get is always very far from the reality (sometimes half the time I get using the Waze App on Android).

So I would like to try Google Maps.

I found some info here, you need to get a Google API key for free and you have a daily limimation on using it (if I remember well something like 1000).
https://developers.google.com/maps/docu ... Parameters


I tried using the first and simple http, https://maps.googleapis.com/maps/api/di ... zzzzzzzzzz and I got a result like this.

Code: Select all

{
   "geocoded_waypoints" : [
      {
         "geocoder_status" : "OK",
         "place_id" : "zzzzzz",
         "types" : [ "route" ]
      },
      {
         "geocoder_status" : "OK",
         "place_id" : "aaaaaaaaa",
         "types" : [ "street_address" ]
      }
   ],
   "routes" : [
      {
         "bounds" : {
            "northeast" : {
               "lat" : xxxxxx,
               "lng" : yyyyyy
            },
            "southwest" : {
               "lat" : xxxxxx,
               "lng" : yyyyyy
            }
         },
         "copyrights" : "Map data ©2016 Google",
         "legs" : [
            {
               "distance" : {
                  "text" : "12,7 km",
                  "value" : 12736
               },
               "duration" : {
                  "text" : "18 min",
                  "value" : 1105
               },
               "end_address" : "xxxxxx",
               "end_location" : {
                  "lat" : xxxxx,
                  "lng" : yyyyyy
               },
               "start_address" : xxxxxx",
               "start_location" : {
                  "lat" : xxxxxx,
                  "lng" : yyyyyy
                  .....
I haven't report all the file, but just the first part, since the total distance and duration are already shown without the needs of a calculation.
And it seems to me more real.

What I don't know is how to get it from a lua script.

Any suggestion?

Thanks
Vittorio

Re: Traffic with Google Maps in Domoticz

Posted: Thursday 07 April 2016 12:15
by Westcott
Hi Vittorio,
Thanks for posting, this could keep me occupied for hours.
Getting a key is particularly easy if you are already a registered Google user.
Reading the data with Lua is 'straightforward', this creates a table of your data -

Code: Select all

commandArray = {}

key     = 'your-api-key'
jsonurl = 'https://maps.googleapis.com/maps/api/directions/json?origin=xxxxxx,yyyyy&destination=xxxxx,yyyyy&key='..key
jsondata    = assert(io.popen(jsonurl))
jsondevices = jsondata:read('*all')
jsondata:close()
JSON = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
data = JSON:decode(jsondevices)
-- Read from the data table, and add to devices
return commandArray
Have a look at this Wiki to see the principal in action -
https://www.domoticz.com/wiki/Real-time ... Lux_sensor...

Re: Traffic with Google Maps in Domoticz

Posted: Thursday 07 April 2016 12:48
by woody4165
Thanks for your reply and piece of code.

This code is very similar to the one found in the Waze traffic script.

What I'm not able to do is to extract the two values I am interested in that are distance/text and duration/text from my previous message.

I know it's maybe OT, since is not related to Domoticz, but to Lua language.

I tried to follow the link, but I get "There is currently no text in this page. You can search for this page title in other pages, search the related logs, or edit this page.".

Re: Traffic with Google Maps in Domoticz

Posted: Thursday 07 April 2016 12:57
by Westcott
Ah, the link above misses the final '.'
There's 3 of them...
It shows how to read from the data table using the names in the returned result.

Re: Traffic with Google Maps in Domoticz

Posted: Thursday 07 April 2016 14:00
by woody4165
ok, thanks, I'll take a look into it and try to use it.

Re: Traffic with Google Maps in Domoticz

Posted: Thursday 07 April 2016 15:15
by woody4165
I'm trying to do it starting from the example, but I'm doing something wrong.

This is the file to read:

Code: Select all

   "geocoded_waypoints" : [
      {
         "geocoder_status" : "OK",
         "place_id" : "xxxxxxx",
         "types" : [ "route" ]
      },
      {
         "geocoder_status" : "OK",
         "place_id" : "xxxxxxxxx",
         "types" : [ "street_address" ]
      }
   ],
   "routes" : [
      {
         "bounds" : {
            "northeast" : {
               "lat" : xxxxx,
               "lng" : xxxxxx
            },
            "southwest" : {
               "lat" : xxxx,
               "lng" : xxxxxx
            }
         },
         "copyrights" : "Map data ©2016 Google",
         "legs" : [
            {
               "distance" : {
                  "text" : "12.7 km",
                  "value" : 12736
               },
               "duration" : {
                  "text" : "18 mins",
                  "value" : 1105
               },
                 ........
 
and here is the full script code

Code: Select all

commandArray={}

json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()

local distance = " "
local duration = " "

key     = 'aaaaaaaaaaaaa'
local jsondata    = assert(io.popen('curl https://maps.googleapis.com/maps/api/directions/json?origin=xxxxxx,yyyyyy&destination=xxxxxx,yyyyyy&key=xxxxxx'))
local jsondevices = jsondata:read('*all')
jsondata:close()
local gmaps = json:decode(jsondevices)

-- Read from the data table, and add to devices
          local distance = gmaps.routes.legs.distance.text
          local duration = gmaps.routes.legs.duration.text

print(duration)
print(distance)

return commandArray
I tried the curl string in a browser and I get it correctly.

I think, based on the example in the Wiki, that I should read routes/legs/distance/text

so I do

Code: Select all

local distance = gmaps.routes.legs.distance.text
and this is where I get error

Code: Select all

2016-04-07 15:12:08.007 Error: EventSystem: in test_gmaps: [string "---------------------------------..."]:24: attempt to index field 'legs' (a nil value)
The gmaps.routes.legs.distance.text should be different?

Thanks

Re: Traffic with Google Maps in Domoticz

Posted: Thursday 07 April 2016 18:04
by Westcott
Very strange - printing 'jsondevices' gives -
{
"error_message" : "Invalid request. Missing the 'destination' parameter.",
"routes" : [],
"status" : "INVALID_REQUEST"
}
Printing the URL and copying it to a browser it works OK.

Re: Traffic with Google Maps in Domoticz

Posted: Thursday 07 April 2016 18:23
by woody4165
Found this exactly for same Google maps API.

http://stackoverflow.com/questions/3053 ... n-paramete

But don't understand the answer... :-(

Re: Traffic with Google Maps in Domoticz

Posted: Thursday 07 April 2016 19:32
by Westcott
Yes I found it also.
It means adding some double quotes around the URL -

Code: Select all

key     = 'key'
jsonurl = 'curl "https://maps.googleapis.com/maps/api/directions/json?destination=41.765307,12.3677014&origin=41.8234588,12.4437439&key='..key..'"'
jsondata = assert(io.popen(jsonurl))
This makes the query run, but the returned data is now too long for a string.
I'm looking into that.

Re: Traffic with Google Maps in Domoticz

Posted: Thursday 07 April 2016 20:32
by woody4165
Probably I found the issue.

The file returned contains this string:

Code: Select all

"html_instructions" : "Head \u003cb\u003esoutheast\u003c/b\u003e on \u003cb\u003eVia Madras\u003c/b\u003e toward \u003cb\u003eVia Calcutta\u003c/b\u003e",
                     "polyline" : {
                        "points" : "ssg~Fkl}jA`B}B"
                        
I think that the "points" : "ssg~Fkl}jA`B}B" is the issue. I contains some braces!!!

Infact if I print the jsondevices, I can see the log until here:

Code: Select all

"html_instructions" : "Head \u003cb\u003esoutheast\u003c/b\u003e on \u003cb\u003eVia Madras\u003c/b\u003e toward \u003cb\u003eVia Calcutta\u003c/b\u003e",
"polyline" : {
The fact is that I don't know how to "bypass" this...

Re: Traffic with Google Maps in Domoticz

Posted: Friday 08 April 2016 21:21
by Westcott
Well, I think I've cracked it, try-

Code: Select all

          local distance = data.routes[1].legs[1].distance.text
          local duration = data.routes[1].legs[1].duration.text

Re: Traffic with Google Maps in Domoticz

Posted: Friday 08 April 2016 23:37
by woody4165
It's WORKING!!!

Thanks.

What was the cause?

Re: Traffic with Google Maps in Domoticz

Posted: Friday 08 April 2016 23:54
by Westcott
It must be because the Google Json data allows for multiple routes, each with multiple legs.
We had to select route 1, leg 1.

Re: Traffic with Google Maps in Domoticz

Posted: Saturday 09 April 2016 16:53
by remb0
Can you add this to the wiki as alternative for waze?

Re: Traffic with Google Maps in Domoticz

Posted: Saturday 09 April 2016 18:20
by woody4165
I have prepared a "clean" script, considering that I have very poor knowledge of programming.

And I don't know how to update the wiki, so if someone can make it for me, I will appreciate it, since this is not the right place to ask for help on how to update it...

What is needed is a "Google Maps APIs for Web" and you can get it at https://developers.google.com/maps/web/

You need to know the starting point and destination coordinates (in the Google Map web page just set your itinerary and you will see the coordinates in the url).

You can modify when to go in to the calculation loop, for me only during weekdays and only between 7AM and 9AM.

It takes out from the generated data, decoded with Json, the total duration, you can have it as text (duration) or as a number (mins) and the total distance, only as text.

I'm returning text in my idx device, using duration.

Code: Select all

---------------------------------
-- Script to calculate duration and distance between two points using Google Maps
-- Autor : woody4165 based on Neutrino Traffic with Waze
-- Date : 9 April 2016 
-- Need a text device (using duration) or an integer (using mins)
---------------------------------
commandArray={}

    time = os.date("*t")
    day = tonumber(os.date("%w"))
    
    idx = 'nn'
    -- If a weekday and time between 7AM and 9AM
    if ((day > 0 and day < 6) and (time.hour > 6 and time.hour < 10)) then
    
        -- Every 10 minutes
        if((time.min % 10)==0) then
    
            --import JSON.lua library
            json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
    
            -- variables --
            -- Coordinates starting point
            fromx="xx.xxxxxxx"
            fromy="yy.yyyyyyy"
            -- Coordinates destination point
            tox="xx.xxxxxxx"
            toy="yy.yyyyyyy"
            -- Google Api Key
            key     = 'zzzzzzzzzzzzzzzzzzzzzz'

            -- get data from Google Maps and decode it in gmaps
            local jsondata    = assert(io.popen('curl "https://maps.googleapis.com/maps/api/directions/json?origin='..fromx..','..fromy..'&destination='..tox..','..toy..'&key='..key..'"'))
            local jsondevices = jsondata:read('*all')
            jsondata:close()
            local gmaps = json:decode(jsondevices)
    
            -- Read from the data table, and extract duration and distance in text
            distance = gmaps.routes[1].legs[1].distance.text
            duration = gmaps.routes[1].legs[1].duration.text
    
            -- mins is only the number part of duration (for evaulation purpose or to return a number in a number device)
            for minutes in string.gmatch(duration, "%d+") do mins = tonumber(minutes) end
    
            -- return a text to the device (eg. 12 mins)
            commandArray[1]={['UpdateDevice'] =idx..'|0|' .. tostring(duration)}
        end
    
    end

return commandArray
What I'm missing is this.
I would like to receive a Telegram message with the traffic, but since the script is executed more than once every 10 minutes, I get something like 6-8 messages one after the other on the tenth minutes.

I was not able to find a way to avoid this, so I gave up.

Thanks!

Re: Traffic with Google Maps in Domoticz

Posted: Saturday 09 April 2016 18:30
by jvdz
What have you named this script? script_device_xxxx.lua or script_time_xxxx.lua?
Should be the latter.

Jos

Re: Traffic with Google Maps in Domoticz

Posted: Saturday 09 April 2016 18:39
by woody4165
I have this script in Setup->More Options->Events, is not saved as a file, but of course it can be done like this.

I have understood the script_device_xxxx function, but how it works the script_time_xxxx ?

Re: Traffic with Google Maps in Domoticz

Posted: Saturday 09 April 2016 18:44
by jvdz
Ok, so you use the internal editor. What have you selected ? LUA & All?
That should be LUA & Time.

Jos

Re: Traffic with Google Maps in Domoticz

Posted: Saturday 09 April 2016 20:16
by woody4165
Thanks!!

I haven't noticed this, and now it's working perfectly, one message every 10 minutes.

I have changed also two things I noticed in the script.

I've added the parameter &departure_time=now to the curl so it's sure it takes the actual duration.

I've modified the duration in duration_in_traffic since this is the real value that consider also the actual traffic.

So now the script is:

Code: Select all

---------------------------------
-- Script to calculate duration and distance between two points using Google Maps
-- Autor : woody4165 based on Neutrino Traffic with Waze
-- Date : 9 April 2016 
-- Need a text device (using duration) or an integer (using mins)
---------------------------------
commandArray={}

    time = os.date("*t")
    day = tonumber(os.date("%w"))
    
    idx = 'nn'
    -- If a weekday and time between 7AM and 9AM
    if ((day > 0 and day < 6) and (time.hour > 6 and time.hour < 10)) then
    
        -- Every 10 minutes
        if((time.min % 10)==0) then
    
            --import JSON.lua library
            json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
    
            -- variables --
            -- Coordinates starting point
            fromx="xx.xxxxxxx"
            fromy="yy.yyyyyyy"
            -- Coordinates destination point
            tox="xx.xxxxxxx"
            toy="yy.yyyyyyy"
            -- Google Api Key
            key     = 'zzzzzzzzzzzzzzzzzzzzzz'

            -- get data from Google Maps and decode it in gmaps
            local jsondata    = assert(io.popen('curl "https://maps.googleapis.com/maps/api/directions/json?origin='..fromx..','..fromy..'&destination='..tox..','..toy..'&departure_time=now&key='..key..'"'))
            local jsondevices = jsondata:read('*all')
            jsondata:close()
            local gmaps = json:decode(jsondevices)
    
            -- Read from the data table, and extract duration and distance in text
            distance = gmaps.routes[1].legs[1].distance.text
            duration = gmaps.routes[1].legs[1].duration_in_traffic.text
    
            -- mins is only the number part of duration (for evaulation purpose or to return a number in a number device)
            for minutes in string.gmatch(duration, "%d+") do mins = tonumber(minutes) end
    
                -- send a Telegram message with status update (replace xxxxxxx with chatid and yyyyyyyyy with bot key)
                -- In case you don't want to receive Telegram message, just remove or comment next two lines
            message = mins..'  mins to go to office at  '..time.hour..':'..time.min..' !!!'
            os.execute('curl --data chat_id=xxxxxxxxxx--data-urlencode "text='..message..'"  "https://api.telegram.org/botyyyyyyyyyyyyyyyyy/sendMessage" ')

    
            -- return a text to the device (eg. 12 mins)
            commandArray[1]={['UpdateDevice'] =idx..'|0|' .. tostring(duration)}
        end
    
    end

return commandArray

Traffic with Google Maps in Domoticz

Posted: Sunday 10 April 2016 0:26
by G3rard
Thanks all for sharing these scripts. Works a lot better then using Waze.