Kalendarz google w fibaro

  • 9 Odpowiedzi
  • 22641 Wyświetleń

0 użytkowników i 1 Gość przegląda ten wątek.

*

Offline marcinwojciesz

  • Moderator Globalny
  • ***** 122
  • 3
  • Nazwa i wersja ID: HC2 4.042, Sterbox
Kalendarz google w fibaro
« dnia: Marzec 28, 2018, 12:59:45 pm »
Witajcie.
Od jakiegoś czasu chciałem wyświetlać dane z kalendarza Google na aplikacji F.
Znalazłem na innym ale mniej popularnym forum człowieka o nazwie  jcichon01@  który popełnił już coś takiego.
przeniosłem do siebie. A teraz krok po kroku:

1. Zakładam kalendarz Googla i dodaję testowe wydarzenie,
2. Wchodzę w ustawienia i udostępnianie tego kalendarza - znajduje "Tajny adres w formacie iCal" kopiuje,
3. Robie zmienne "GCalendar" bez wartości, druga "Month" i przypisuje dla niego "Styczeń", "Luty", ....."Grudzień" (nie pomyl się ąę musi być i duża litera),
4. Zmienna Month ustawiam na dany miesiąc (myślę, że to zautomatyzuje lada dzień),
5. Dodaje Wirtualne urządzenia Calendar_Bookings (1).vfib - (w zał.)
6. dodaje scene - która musi się odpalać tyle ile chcemy żeby aktualizować nasz kalendarz - (w zał.),
--[[
%% properties

%% globals
--]]

--[[
---------------------------------------------------------------
---------     Google Calendar synchronization         ---------
---------               version 1.2                   ---------
---------------------------------------------------------------

CHANGELOG:
ver 1.0
- initial
ver 1.1
- added support for events defined in .ics file as "recurring".
  Few basic recurrance types are added
ver 1.2
- added handling of "all day" events; small bug fixing;

Scene used to synchronize Google Calendar with HC2. Synchronization
results are stored in the Global Variable and can be used by other
scenes or virtual devices by reading its content using for example
following:
 local jsonMyGCal = fibaro:getGlobal("GCalendar");
 local MyGCal     = json.decode(jsonMyGCal)
 for i = 1, #MyGCal do
   print (MyGCal[i].Name)
   print (MyGCal[i].StartDate)
   print (MyGCal[i].EndDate)
   print (MyGCal[i].WholeDay) - is set to "Yes" or "No"
 end

Part of the code after "baran" from http://www.zwave-community.it/

-- LIST OF GLOBAL VARIABLES NEEDED ------------------------------------------
"GCalendar" holds synchronized Google Calendar events
            Can be read using json.decode(fibaro:GetGlobal("GCalendar"))
        and used in other scenes based on GCalendar events
"Month"     Used by this script to recognize the month for sychronization.
            Idea is to synchronize GCal events for this month & current year
            only. This global variable is updated with Sankotronic's
            "Main Scene for time based events"
--]]

--- Link to private calendar file
---  fill it with the link to you google calendar file
---  https://calendar.google.com/calendar/ical/XXXXXXXX%40gmail.com/private-googleid/yyyyy.ics
---  link can be retrieved from Google Calendar settings page
---  --> ICAL file in Calendar address - page "Calendar XXX details"

-----------------------------------------------------------------
--- VARIABLES
-----------------------------------------------------------------

local gCalUrl ="https://calendar.google.com/calendar/ical/xxxxxxxxxxxxxxx/basic.ics"
local HC = net.HTTPClient()

--- Time zone correction: 1 = gmt+1 2=gmt+2 ecc ecc
local timeZone      = 1;

-- debugging variables
local responseDebug = 0;   -- will show the content of GCal file after retrival
local eventDebug    = 0;   -- allows you to trace the parsing process
local outputDebug   = 0;   -- shows the event table in the structured form along with
                           -- global HC2 variable
local recurDebug    = 0;   -- extra debugging for recurring events                       

-- other variables
local MyGCal        = {}
local currentMonth = fibaro:getGlobalValue("Month")

-- use the table to get the mapping translated into your local language
local monthMapping =
{
    [ "Styczeń" ]   = "January",
    [ "Luty" ]     = "February",
  [ "Marzec" ]     = "March",
    [ "Kwiecień" ]   = "April",
    [ "Maj" ]     = "May",
    [ "Czerwiec" ]   = "June",
    [ "Lipiec" ]     = "July",
    [ "Sierpień" ]    = "August",
    [ "Wrzesień" ]   = "September",
    [ "Październik" ] = "October",
  [ "Listopad" ]   = "November",
  [ "Grudzień" ]   = "December"
  }

local monthNumbers =
{
    [ "January" ]   = 1,
    [ "February" ]   = 2,
  [ "March" ]     = 3,
    [ "April" ]       = 4,
    [ "May" ]     = 5,
    [ "June" ]       = 6,
    [ "July" ]       = 7,
    [ "August" ]      = 8,
    [ "September" ] = 9,
    [ "October" ]     = 10,
  [ "November" ]   = 11,
  [ "December" ]   = 12
  }

local days_in_month = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };


-----------------------------------------------------------------
--- FUNCTIONS
-----------------------------------------------------------------

function logbug(color, message)
  fibaro:debug(string.format('<%s style="color:%s;">%s</%s>', "span", color, message, "span"));
end

-- is this a whole day event?
function CheckIfWholeDay(startDate, endDate);
 
  if tonumber(os.date("%H", startDate)) == 0 and
     tonumber(os.date("%M", startDate)) == 0 and
     tonumber(os.date("%S", startDate)) == 0 and
     tonumber(os.date("%H", endDate)) == 0 and
     tonumber(os.date("%M", endDate)) == 0 and
     tonumber(os.date("%S", endDate)) == 0 then
    return "Yes";
  else
    return "No";
  end;
end; 

-- append the entry to Calendar variable
function AppendToGCal(startDate, endDate, ev_name);

  if tonumber(os.date("!%Y",startDate)) == tonumber(os.date("!%Y", os.time()))  and
     tostring(os.date("!%B",startDate)) == tostring(monthMapping[currentMonth])         
  then         
    MyGCal[#MyGCal+1] = {
                          Name       = ev_name,
                          StartDate  = startDate,
                          EndDate    = endDate,
                          WholeDay   = CheckIfWholeDay(startDate, endDate)
                        };
    if eventDebug == 1 then
      if MyGCal[i].WholeDay == "Yes" then
        logbug("orange", "Wholeday event.");
      end;   
      logbug("gray", "Record added. Event: "..ev_name..", Start: "..startDate..", End: "..endDate);
    end;                               
  else
    if eventDebug == 1 then
      logbug("darkgray", "Record not within selection criteria, skipping...");
    end;   
  end;
end

--- Fetch the content of GCal - GET HTML
function gCal_GetICalData()
HC:request(
   gCalUrl,
   {
     success = function(response)
       gCalRead_2(response.data)
      end,
     error =  httpError,
     options = {method = "GET" }
   }
 )
end

function AppendRecuringEntry(recurance, startDate, endDate, name)
 
  local i = 1;
  local l_rule;
  local l_finish;
  local l_multiplier;
 
  -- is there delimiter like "until", "count"?
  l_rule = "NONE";
  l_finish = "No";

  for l = 1, #recurance do
    -- split the lines               
    recurance[l] = mysplit(recurance[l], "=");

    if recurance[l][1] == "COUNT" then
      l_rule    = "COUNT";
      l_ruleEnd = recurance[l][2];
    elseif  recurance[l][1] == "UNTIL" then
      l_rule    = "UNTIL";
      l_ruleEnd = gCal_UTCTimePhrase(recurance[l][2]);
    end;
 
  end;

  if l_ruleEnd == nil then l_ruleEnd = "not delimited" end; 

  if recurDebug == 1 then
      logbug("lighgray", "Recuring event: "..name..", Baseline date: "..(os.date("%x",startDate)));
      if l_ruleEnd == "not delimited" then
        logbug("gray", "Frequency: "..recurance[1][2]..", Rule: "..l_rule..", End by: "..l_ruleEnd);
      else
        logbug("gray", "Frequency: "..recurance[1][2]..", Rule: "..l_rule..", End by: "..(os.date("%x",l_ruleEnd)));       
      end
  end;   

  -- recognize the dates for recurring events
  while ( tonumber(os.date("%m",startDate)) <= tonumber(monthNumbers[monthMapping[currentMonth]]) -- not exceeding given month
    and tonumber(os.date("!%Y",startDate)) == tonumber(os.date("!%Y", os.time()))                 -- and current year
    and  l_finish == "No" )                                                                       -- should I stop searching?

  do
    if     recurance[1][2] == "WEEKLY"  then l_multiplier = 7;
    elseif recurance[1][2] == "DAILY"   then l_multiplier = 1;
    elseif recurance[1][2] == "MONTHLY" then l_multiplier = tonumber(days_in_month[tonumber(os.date("%m",startDate))]);
    else   l_multiplier = 9999; -- no handling
    end;
   
    if l_multiplier == 9999 then
      l_finish = "Yes";
      if recurDebug == 1 then
          logbug("light red", "Unhandled rule");
      end;     
    else 
      startDate = startDate + l_multiplier * (60 * 60 * 24 );
      endDate   = endDate + l_multiplier * (60 * 60 * 24 ); 
   
      if recurDebug == 1 then
          logbug("gray", "Next occurance within sycnhronization period: "..os.date("!%c",startDate));
      end;   

      AppendToGCal(startDate, endDate, name);

      -- did I reach the end?
      if l_rule == "COUNT" then
        if tonumber(l_ruleEnd) == i then l_finish = "Yes" end;
      elseif rule == "UNTIL" then
        if  startDate >= l_ruleEnd then l_finish = "Yes" end;
      end;
     
      i = i + 1;
    end; 
  end;       
               
end

-- parse the entries
function gCalRead_2(data)

local l_StartDate
local l_EndDate
local l_Name
local l_Recurring
local l_RRule
local l_CurrentBlock
 
data = string.gsub(data, "\r", "") -- Remove CarageReturn
lines = mysplit(data, "\n")        -- Split GCal string

for i,line in ipairs(lines) do
   
  if responseDebug == 1 then
     logbug("gray", "Line: "..i.." RESP "..line)
  end
 
  values = mysplit(line, ":")
 
  if values[1] == "BEGIN" then
      if values[2] == "VEVENT" then
        l_CurrentBlock = "VEVENT";  -- we're at the beginning of event definition
        l_RRule = "No";             -- no recurrance by default
      end
  end
     
   
  if l_CurrentBlock == "VEVENT" then
  --- get the GCal events START,STOP and
  --- v 1.1 for recurring events - time zone included in the timestamp
  ---       syntax as follows: DTSTART;TZID=America/New_York:20120503T180000
  --- v 1.2 in case DTSTART/DTEND contains date only -
  ---       it is whole/multiple day event. e.g. DTSTART;VALUE=DATE:20170312
   
    if values[1] == "DTSTART"
        or string.sub(values[1], 1, 12)  == "DTSTART;TZID"
        or string.sub(values[1], 1, 13)  == "DTSTART;VALUE"
        then
            l_StartDate  = gCal_UTCTimePhrase(values[2])
        end
    if values[1] == "DTEND"
        or string.sub(values[1], 1, 10)  == "DTEND;TZID"
        or string.sub(values[1], 1, 11)  == "DTEND;VALUE"
        then
            l_EndDate = gCal_UTCTimePhrase(values[2])
        end
    if values[1] == "SUMMARY"
        then
            l_Name = values[2]
        end
    if values[1] == "RRULE"
        then
            l_Recurring = mysplit(values[2], ";");
            l_RRule = "Yes";
        end 
    if values[1] == "END"
        then
            l_CurrentBlock = "None"
     
--   filter to the events of the current month (and year)
            if l_RRule == "No"
               then
                  AppendToGCal(l_StartDate, l_EndDate, l_Name);
               else     
                  AppendRecuringEntry(l_Recurring, l_StartDate, l_EndDate, l_Name);       
            end; -- recurance
    end;
  end;
   
  end

-- Events are collected
-- pack it into global variable
gCal_OutputToGlobalVar()
 
end

-- parse the Google dates
function gCal_UTCTimePhrase(data)

--- v 1.2 whole-day events are defined by date only

local MyDate = {}
 
MyDate["Year"] = tonumber(string.sub(data, 1, 4))
MyDate["Month"] = tonumber(string.sub(data, 5, 6))
MyDate["Day"] = tonumber(string.sub(data, 7, 8))

if tonumber(string.sub(data, 10, 11)) == nil then -- whole-day event
  MyDate["Hour"] = tonumber("00");
  MyDate["Minute"] = tonumber("00");
  MyDate["Second"] = tonumber("00");
else;
  MyDate["Hour"] = tonumber(string.sub(data, 10, 11))
  MyDate["Minute"] = tonumber(string.sub(data, 12, 13))
  MyDate["Second"] = tonumber(string.sub(data, 14, 15))
end;

return os.time{year=MyDate["Year"], month=MyDate["Month"], day=MyDate["Day"], hour=MyDate["Hour"], min=MyDate["Minute"],sec=MyDate["Second"]}
 
end

function mysplit(inputstr, sep)
 
  if sep == nil then
     sep = "%s"
  end
 
  local t={} ; i=1
    for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
      t[i] = str
      i = i + 1
    end
   
  return t
 
end


-- Move Events into local HC2Table
function gCal_OutputToGlobalVar()

local i

CurrentTimeAndDate = os.time()
 
if outputDebug == 1 then
  logbug("blue", "Current time: "..os.date("%c",CurrentTimeAndDate))     

--sort to have it in chronological order
  table.sort(MyGCal,function(a,b) return a.StartDate < b.StartDate end)
   
  for i = 1, #MyGCal do
     MyGCal[i].StartDate = MyGCal[i].StartDate + timeZone*3600;
     MyGCal[i].EndDate = MyGCal[i].EndDate + timeZone*3600;     
     logbug("lightgreen", "Event name: "..MyGCal[i].Name); 
     if MyGCal[i].WholeDay == "Yes" then
        logbug("gray", "Start date: "..os.date("%x",MyGCal[i].StartDate));
        logbug("gray", "Finish date: "..os.date("%x",MyGCal[i].EndDate));     
        logbug("gray", "Wholeday event: "..MyGCal[i].WholeDay);
     else
        logbug("gray", "Start date: "..os.date("%c",MyGCal[i].StartDate));
        logbug("gray", "Finish date: "..os.date("%c",MyGCal[i].EndDate));       
     end;   
  end;
end

logbug("gray", "Added TOTAL of: "..#MyGCal.." calendar records.")

-- move and pack into HC2 global variable
jsonMyGCal = json.encode(MyGCal);
 
fibaro:setGlobal("GCalendar", jsonMyGCal);
 
if outputDebug == 1 then
   logbug("yellow", "MyGCal variable content: ");
   logbug("gray", jsonMyGCal);
end   
 
end


-----------------------------------------------------------------
--- MAIN Code
-----------------------------------------------------------------

-- update calendar
gCal_GetICalData();

logbug("green", "Synchonization completed");
7. W scenie wklejam to co skopiowałem w pkt. 2. w miejsce gdzie już jest wpis a w nim masę xxxxxxxx,
8. Odpalam scenę,
9. Odpalam urządzonko,
10. Jeśli nie ma wyników od razu to czekam parę sek. i uzupełniają się dane,
11. (W planie mam) udostępniam kalendarz żonie i razem możemy dodawać do niego pozycje.

Mam nadzieję, że komuś się to przyda.
« Ostatnia zmiana: Marzec 28, 2018, 01:01:47 pm wysłana przez marcinwojciesz »
*

Offline wojtas810

  • *** 205
  • 3
  • Nazwa i wersja ID: wojtas810
Odp: Kalendarz google w fibaro
« Odpowiedź #1 dnia: Kwiecień 02, 2018, 11:12:15 am »
Powiedz mi tak z ciekawości oprócz wyświetlania wydarzeń do czego jeszcze jest to przydatne ?
*

Offline marecki_0luk1

  • Administratorzy
  • ***** 430
  • 26
  • Nazwa i wersja ID: HC3 5.070.42 / HC2 4.600
Odp: Kalendarz google w fibaro
« Odpowiedź #2 dnia: Kwiecień 02, 2018, 06:09:48 pm »
np. push na telefon ze za chwile zebranie u dziecka w szkole ? :) albo lista zakupow od zony :)
*

Offline marcinwojciesz

  • Moderator Globalny
  • ***** 122
  • 3
  • Nazwa i wersja ID: HC2 4.042, Sterbox
Odp: Kalendarz google w fibaro
« Odpowiedź #3 dnia: Kwiecień 03, 2018, 08:27:36 am »
no u mnie działa tak że przypomina smykom o:
- karmienu rybek
- braniu lekarstw
- inne wpisywane na bieżąco.
Chciałbym aby moja gadaczka jeszcze to czytała o danej godzinie, nie wiem jak się za to zabrać za bardzo więc jeśli ktoś coś to poproszę o pomoc.
*

Offline wojtas810

  • *** 205
  • 3
  • Nazwa i wersja ID: wojtas810
Odp: Kalendarz google w fibaro
« Odpowiedź #4 dnia: Kwiecień 10, 2018, 08:18:11 pm »
no u mnie działa tak że przypomina smykom o:
- karmienu rybek
- braniu lekarstw
- inne wpisywane na bieżąco.
Chciałbym aby moja gadaczka jeszcze to czytała o danej godzinie, nie wiem jak się za to zabrać za bardzo więc jeśli ktoś coś to poproszę o pomoc.

A masz sonosa ??


No dobra ale te wartosci które opisaliście w standardzie są w google kalendarz i szybciej się je wpisuje i wyświetla komunikaty wiec dalej średnio widzę zastosowanie przydatne i nie powielanie
*

Offline marcinwojciesz

  • Moderator Globalny
  • ***** 122
  • 3
  • Nazwa i wersja ID: HC2 4.042, Sterbox
Odp: Kalendarz google w fibaro
« Odpowiedź #5 dnia: Kwiecień 11, 2018, 08:00:09 am »
Nie mam Sonosa ale za to mam PAW Serwer i działa świetnie. Masz racje w standardzie jest ale pod warunkiem ze dzieci mają telefon.
Nie będę tu bronił tego produktu - mi przydaje się. Tylko brakuje gadania.
*

Offline wojtas810

  • *** 205
  • 3
  • Nazwa i wersja ID: wojtas810
Odp: Kalendarz google w fibaro
« Odpowiedź #6 dnia: Kwiecień 11, 2018, 09:25:00 pm »
Ok
Spoko ja tylko pytam ponieważ może jest jakieś ukryte dno którego nie zauważyłem - dlatego dopytuję.
Nie ukrywam ze ja jestem zwolennikiem prostoty i nie powielania :)
*

Offline vandi

  • * 20
  • 6
Odp: Kalendarz google w fibaro
« Odpowiedź #7 dnia: Czerwiec 23, 2018, 02:48:02 pm »
Zrobilem tak na szybko bez zbytniego grzebania się w kodzie..
local currentMonth = tonumber(os.date('%m'))
local monthMapping = { 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'}
Tak, żeby nie trzeba było korzystać ze zmiennej globalnej "month', ani miesięcy wpisywać ręcznie.
Wystarczy podmienić dwie zmienne lokalne: currentMonth i  monthMapping.
Może komuś się przyda.
Pozdrawiam
« Ostatnia zmiana: Czerwiec 23, 2018, 03:30:10 pm wysłana przez vandi »
*

Offline vandi

  • * 20
  • 6
Odp: Kalendarz google w fibaro
« Odpowiedź #8 dnia: Październik 05, 2018, 07:21:27 pm »
więc tak Panowie..
Nie pasował mi ten skrypt który @marcinwojciesz wstawłeś.
Zawiły, zagmatwany, i nie pasujący do mojego projektu.
  Trochę poszperałem w google API, pomyslałem...
  i wymyśliłem.
  I co najciekawsze.. działa :D
  --================================
  --Synchronizacja kalendarza Google
  local wersja = 1.1
  local autor = 'vandi'
  --================================
  local maxZdarzen = 6
  local ileDniDoPrzodu = 12
  --================================
  local kluczAPI = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
  local idKalendarza = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%40group.calendar.google.com'
  --================================
  local adres = 'https://www.googleapis.com/calendar/v3/calendars/'..idKalendarza..'/events?prettyPrint=false&alwaysIncludeEmail=false&maxResults='..maxZdarzen..'&timeMax='..os.date('%Y-%m-%d',os.time()+ileDniDoPrzodu*24*3600)..'T00%3A00%3A00%2B02%3A00&timeMin='..os.date('%Y-%m-%d', os.time())..'T00%3A00%3A00%2B02%3A00&key='..kluczAPI
  net.HTTPClient():request(adres, {
      success = function(response)
        local osT = function (arg) return os.time({month=string.sub(arg,6,7), day=string.sub(arg,9,10), year=string.sub(arg,1,4), hour=0, min=0, sec=0})  end
        local _dO, g = osT(os.date('%Y-%m-%d'),os.time()), function(a) return 86400*a end
        tab = json.decode(json.decode(json.encode(response)).data).items
        local listaD, listaG = {},{}
        for i in pairs(tab) do
          listaD[#listaD+1], listaG[#listaG+1] = osT(tab[i].start.date), {czas = osT(tab[i].start.date), zdarz = tab[i].summary}
        end
        table.sort(listaD) 
        for i,dK in pairs(listaD) do   
          for i,j in pairs(listaG) do
            for o = 0,  ileDniDoPrzodu do
              if dK == j.czas then
                if (j.czas - _dO) >= 0 and (j.czas - _dO) <= g(o) then
                  o = o == 0 and 'dziś' or o == 1 and 'jutro' or '+'..o
                  print(o..' '..j.zdarz)
                  table.remove(listaG, i)
                  break
                end
              end
            end
          end
        end
      end ,     
      error = function() print('błąd')end,
      options = {method = "GET" }}
  )   
 
  Efekt na dolnym wyświetlaczu. Wisi w kuchni. :)
« Ostatnia zmiana: Grudzień 03, 2018, 06:26:29 pm wysłana przez vandi »
Odp: Kalendarz google w fibaro
« Odpowiedź #9 dnia: Styczeń 29, 2019, 09:20:28 pm »
Witam serdecznie
Wszystko zrobiłem jak w instrukcji ale nie działa