Jump to content

Welcome to Smart Home Forum by FIBARO

Dear Guest,

 

as you can notice parts of Smart Home Forum by FIBARO is not available for you. You have to register in order to view all content and post in our community. Don't worry! Registration is a simple free process that requires minimal information for you to sign up. Become a part of of Smart Home Forum by FIBARO by creating an account.

 

As a member you can:

  •     Start new topics and reply to others
  •     Follow topics and users to get email updates
  •     Get your own profile page and make new friends
  •     Send personal messages
  •     ... and learn a lot about our system!

 

Regards,

Smart Home Forum by FIBARO Team


Search the Community

Showing results for tags 'scenesmove'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • FIBARO Community
    • FIBARO Portal and Forum policy
    • FIBARO
    • Say hello!
    • Off-topics
  • FIBARO Update
    • FIBARO System Update
    • FIBARO Mobile Update
  • FIBARO Community Support
    • Scenes and Interface
    • FIBARO Products
    • FIBARO Mobile
    • FIBARO HomeKit
    • FIBARO Assistant Integrations
    • Other Devices / Third-party devices
    • Tutorials and Guides
    • Home Automation
    • Suggestions
  • FIBARO Społeczność
    • FIBARO
    • Przywitaj się!
    • Off-topic
  • FIBARO Aktualizacja
    • FIBARO System Aktualizacja
    • FIBARO Mobile Aktualizacja
  • FIBARO Wsparcie Społeczności
    • Sceny i Interfejs
    • FIBARO Urządzenia
    • FIBARO Mobilnie
    • FIBARO HomeKit
    • Integracja z Amazon Alexa i Google Home
    • Urządzenia Firm Trzecich
    • Poradniki
    • Automatyka Domowa
    • Sugestie

Categories

  • Scenes
  • Virtual Devices
  • Quick Apps
  • Icons

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Facebook


Google+


Skype


Website URL


WhatsApp


Country


Gateway/s


Interests

  1. Playing around with my MagicMirror installation, for now i just run app in servermode only and to my iPad, no mirror installation yet. Installing was no rocket sience, just followed the instructions. Added a couple of modules to play around with, first one out was weather data from wunderground and then a module with name syslog. So together with MagicMirror and a scene in my HC2 i can send data to be shown in the syslog module, thats nice Here is the lua scene code (just my first draft) --[[ %% properties %% events %% globals yeasterdayKW test --]] -- USER SETTINGS -- MMip = '192.168.0.137' MMport = '8080' local trigger = fibaro:getSourceTrigger(); local daysoftheweek={"Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag"} local yesterday = urlencode(daysoftheweek[os.date("*t").wday-1]) function urlencode(str) if (str) then str = string.gsub(str, "\n", "\r\n") str = string.gsub(str, "([^%w ])", function (c) return string.format ("%%%02X", string.byte(c)) end) str = string.gsub (str, " ", "+") end return str end function MM(types,data) local function getMethod(requestUrl, successCallback, errorCallback) local http = net.HTTPClient() http:request(requestUrl, { options = { method = 'GET', headers = { }, }, success = successCallback, error = errorCallback }) end local url = 'http://'..MMip..':'..MMport..'/syslog?type='..types..'&message='..data getMethod(url, function(resp) print(resp.data) end, function(err) print('error' .. err) end ) end if (trigger['type'] == 'global') then if trigger['varName'] == 'yeasterdayKW' then MM('INFO',yesterday..'+'..fibaro:getGlobal(trigger['varName'])..'+'..'kWh') elseif trigger['varName'] == 'test' then MM('ERROR',fibaro:getGlobal(trigger['varName'])..'+'..'variabel') end elseif (trigger['type'] == 'other') then print('Scene started by other.') end
  2. Hi, I have two central scene event 'scenes' that represent two different button press actions on one device (Remotec ZRC90) --[[ %% properties %% events 1425 CentralSceneEvent 4 Pressed %% globals --]] local MorningSceneID = 463 local startSource = fibaro:getSourceTrigger(); if ( ( true ) or startSource["type"] == "other" ) then fibaro:startScene(MorningSceneID); -- morning scene end and --[[ %% properties %% events 1425 CentralSceneEvent 3 Pressed2 %% globals --]] local HomeSceneID = 488 local startSource = fibaro:getSourceTrigger(); if ( ( true ) or startSource["type"] == "other" ) then fibaro:startScene(HomeSceneID); -- home scene end Does anybody know how to combine into one scene as this device has 8 buttons/4 options per button (32 events) and I'm trying not to end up with 32 separate scenes the api device dump is as follows... {"id":1425,"name":"Hall Scene Controlle","roomID":5,"type":"com.fibaro.remoteController","baseType":"com.fibaro.actor","enabled":true,"visible":true,"isPlugin":false,"parentId":1424,"remoteGatewayId":0,"interfaces":["battery","zwave","zwaveCentralScene","zwaveWakeup"],"properties":{"parameters":[],"zwaveCompany":"Remotec","zwaveInfo":"2,4,5","zwaveVersion":"1.1","wakeUpTime":0,"pollingTimeSec":0,"batteryLevel":"96","batteryLowNotification":"true","centralSceneSupport":"[{\"keyAttributes\":[\"Pressed\",\"Released\",\"HeldDown\",\"Pressed2\"],\"keyId\":1},{\"keyAttributes\":[\"Pressed\",\"Released\",\"HeldDown\",\"Pressed2\"],\"keyId\":2},{\"keyAttributes\":[\"Pressed\",\"Released\",\"HeldDown\",\"Pressed2\"],\"keyId\":3},{\"keyAttributes\":[\"Pressed\",\"Released\",\"HeldDown\",\"Pressed2\"],\"keyId\":4},{\"keyAttributes\":[\"Pressed\",\"Released\",\"HeldDown\",\"Pressed2\"],\"keyId\":5},{\"keyAttributes\":[\"Pressed\",\"Released\",\"HeldDown\",\"Pressed2\"],\"keyId\":6},{\"keyAttributes\":[\"Pressed\",\"Released\",\"HeldDown\",\"Pressed2\"],\"keyId\":7},{\"keyAttributes\":[\"Pressed\",\"Released\",\"HeldDown\",\"Pressed2\"],\"keyId\":8}]","configured":"true","dead":"false","defInterval":"0","deviceControlType":"0","deviceIcon":"103","emailNotificationID":"0","emailNotificationType":"0","endPointId":"0","liliOffCommand":"","liliOnCommand":"","log":"","logTemp":"","manufacturer":"","markAsDead":"true","maxInterval":"0","minInterval":"0","model":"","nodeId":"196","parametersTemplate":"0","productInfo":"82,84,0,1,133,16,1,1","pushNotificationID":"0","pushNotificationType":"0","remoteGatewayId":"0","saveLogs":"true","serialNumber":"","smsNotificationID":"0","smsNotificationType":"0","stepInterval":"0","useTemplate":"false","userDescription":""},"actions":{"reconfigure":0,"setInterval":1},"created":1468671788,"modified":1468671788,"sortOrder":414} Thanks -Frank SOLUTION local pressSource = fibaro:getSourceTrigger()["event"]["data"] --get data what was pressed --fibaro:debug(json.encode(pressSource)) -- Button 1 to 8 when button is PRESSED once if (tostring(pressSource["keyAttribute"]) == "Pressed") then if (tostring(pressSource["keyId"]) == "1") then fibaro:debug('Key 1 pressed once') -- replace with scene you want executed elseif (tostring(pressSource["keyId"]) == "2") then fibaro:debug('Key #2 pressed once') -- replace with scene you want executed elseif (tostring(pressSource["keyId"]) == "3") then fibaro:debug('Key #3 pressed once') -- replace with scene you want executed elseif (tostring(pressSource["keyId"]) == "4") then fibaro:debug('Key #4 pressed once') -- replace with scene you want executed elseif (tostring(pressSource["keyId"]) == "5") then fibaro:debug('Key #5 pressed once') -- replace with scene you want executed elseif (tostring(pressSource["keyId"]) == "6") then fibaro:debug('Key #6 pressed once') -- replace with scene you want executed elseif (tostring(pressSource["keyId"]) == "7") then fibaro:debug('Key #7 pressed once') -- replace with scene you want executed elseif (tostring(pressSource["keyId"]) == "8") then fibaro:debug('Key 8 pressed once') -- replace with scene you want executed end end Please see post http://forum.fibaro.com/index.php?/topic/21905-at-last-a-wall-mounted-scene-controller-that-works-scene-code-included/ for full scene that works with ZRC90
  3. Hi there, I got the next setting but it does not work properly can someone explane to me whats wrong? I made a variable "timeOfDay" with 3 options "day" "evening" "night" Then I made three scenes on time: 06h30 set variable to day, 18h30 set variable to evening, 23h30 set variable to night. after this I made a scene to turn on the lights in my livingroom asfollow: If sensor livingroom detects motion check variable equals to evening. and lux value < 35 then turn on lights I only checked the triggering device "motion" so this scene will only run if motion is detected en then checks if all statements are true. somehow this works if I manualy activates the "evening" variable I want this because when I go to the bathroom at night I walk though the livingroom and do not want the lights to turn on. So I guess the problem is not in this scene but in de variable scene that sets the variable on time. Or is this thought al wrong? Where can I see witch state the varibale has at this time and do i need to check the "start when home center 2 starts" box? You can see the attach for more details (it's in Dutch) Thanks in advance. Maurice ***UPDATE*** I got it to work now. 2 things I have changed. First I forgot to check the box "start when home center2 starts" and "do not allow alarm to stop scene while alarm is running" Second I had 3 states the variable could be in, "day, evening, night" I brought this back to 2 states "day and night" Now the scene works like a charm. Good luck.
  4. Hi can you help me to start at 8.00 am and stop at 20.00 pm the following sene ? this scene every 300 sec. controls if a device is on or off and if it is off after 300 sec. turn on it. thanks too much --[[ %% autostart %% properties 617 value %% events %% globals --]] local startSource = fibaro:getSourceTrigger(); if(startSource["type"] == "other") then fibaro:call(620, "turnOn"); else if (( tonumber(fibaro:getValue(617, "value")) == 0 )) then setTimeout(function() local delayedCheck0 = false; local tempDeviceState0, deviceLastModification0 = fibaro:get(617, "value"); if (( tonumber(fibaro:getValue(617, "value")) == 0 ) and (os.time() - deviceLastModification0) >= 300) then delayedCheck0 = true; end local startSource = fibaro:getSourceTrigger(); if ( ( delayedCheck0 == true ) or startSource["type"] == "other" ) then fibaro:call(620, "turnOn"); end end, 300000) end end
  5. local daysoftheweek={"Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag"} local day = urlencode(daysoftheweek[os.date("*t").wday-1]) function urlencode(str) if (str) then str = string.gsub (str, "\n", "\r\n") str = string.gsub (str, "([^%w ])", function (c) return string.format ("%%%02X", string.byte(c)) end) str = string.gsub (str, " ", "+") end return str end function MM(data) local function getMethod(requestUrl, successCallback, errorCallback) local http = net.HTTPClient() http:request(requestUrl, { options = { method = 'GET', headers = { }, }, success = successCallback, error = errorCallback }) end local url = 'http://192.168.0.137:8080/syslog?type=INFO&message='..data getMethod(url, function(resp) print(resp.data) end, function(err) print('error' .. err) end ) end MM(day..'+'..fibaro:getGlobal("yeasterdayKW")..'+'..'kWh') Result [DEBUG] 14:13:32: {"status":"success","payload":{"type":"INFO","message":"Söndag 34.96 kWh","timestamp":"2016-10-10T12:13:32.103Z"}} Should be [DEBUG] 14:13:32: {"status":"success","payload":{"type":"INFO","message":"Söndag 34.96 kWh","timestamp":"2016-10-10T12:13:32.103Z"}} so i think my header with utf8 is not correct. If i run url direct in browser it works with same data
  6. Created a LUA function you can use in a scene to upload data to emoncms.org. toEmonCMS = function(id,value,InputKey) local http = net.HTTPClient() -- CHANGE WRITE API KEY FOR EMONCMS local apikey = '1966dcf7b44xxxxxxxxxxxxxxxxxxx' -- SHOULD NOT BE NECESSARY TO EDIT BELOW THIS LINE -- local url = 'https://emoncms.org/input/post.json?json={' http:request(url .. InputKey .. ':' .. fibaro:getValue(id, value).. '}' ..'&apikey='..apikey, { options = { method = "POST", }, success = function(response) fibaro:debug (response.data) end, error = function(err) fibaro: debug ("Error:" .. err) end }) end toEmonCMS(58,'value','Temperature') Example first 319 is id of device, second power is what value you want to upload, third Power is the InputKey in emoncms site Upload power data toEmonCMS(319,'power','Power') Upload temperature data toEmonCMS(58,'value','Temperature')
  7. Aeon KeyFob is missing double click activation (where most of other controllers do have that option), so I'm posting scene below as an example to have double click activation: In order to make this code works for you please follow per below: 1. Set Aeon KeyFob at Scene Mode (Parameter 250 set to 1) 2. Change device ID to your real ID 3. Define global variable "keyFob" --[[ %% properties 433 sceneActivation %% globals --]] local startSource = fibaro:getSourceTrigger() local ButtonPressed = fibaro:getValue(tonumber(startSource["deviceID"]), "sceneActivation") if (fibaro:countScenes() == 2) then fibaro:setGlobal("keyFob", "10") end if (fibaro:countScenes() == 1) then fibaro:sleep(3000) -- wait 3s if next click is coming ButtonPressed = ButtonPressed + tonumber(fibaro:getGlobalValue("keyFob")) if (tonumber(ButtonPressed) == 1) then --UPPER LEFT SHORT fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 2) then -- UPPER LEFT LONG fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 11) then -- UPPER LEFT SHORT DOUBLE NEW KEY fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 12) then -- UPPER LEFT LONG DOUBLE NEW KEY fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 3) then -- UPPER RIGHT SHORT fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 4) then -- UPPER RIGHT LONG fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 13) then -- UPPER RIGHT SHORT DOUBLE NEW KEY fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 14) then -- UPPER RIGHT LONG DOUBLE NEW KEY fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 5) then -- BOTTOM LEFT SHORT fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 6) then -- BOTTOM LEFT LONG fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 15) then -- BOTTOM LEFT SHORT DOUBLE NEW KEY fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 16) then -- BOTTOM LEFT LONG DOUBLE NEW KEY fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 7) then -- BOTTOM RIGHT SHORT fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 8) then -- BOTTOM RIGHT LONG fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 17) then -- BOTTOM RIGHT SHORT DOUBLE NEW KEY fibaro:debug("Key # " .. ButtonPressed) elseif (tonumber(ButtonPressed) == 18) then -- BOTTOM RIGHT LONG DOUBLE NEW KEY fibaro:debug("Key # " .. ButtonPressed) else fibaro:debug("Key # " .. ButtonPressed .. "not found") end fibaro:setGlobal("keyFob", "0") end Now we've doubled the number of keys from 8 to 16 ! at cost of 3 sec. delay. (The delay of 3 seconds works good for my configuration, but could be changed to fit your system) Of course by adding more delay and minor changes of the code, we can go to triple click and even more... By the way same idea could be implement for other controllers to expand the number of keys.
  8. Distance check is a LUA script to turn on the lights when you’re coming home, for example to turn on the garden light. It uses the GPS functionality of the Fibaro HC2. The script tries to manage the delays or the errors that sometimes there are acquiring the user's location by the Fibaro/GPS and it requires an interval of 1 minute for the Fibaro HC2 parameter "How frequently GPS position from the user’s iPhone should be collected". It has been tested in scenario where you are some kilometers away from home and you are going to home. How it works. You can define four areas: large area and small area, gap area and extra large area. The area are circles around the location of the house. When you enter in the large area the light is turned on and a timer is started. If you reach the small area before the timer has expired the light will be “confirmed on” otherwise the light will be turned off. Perhaps you was not going to home but you have entered in the large area for a while. When the light is “confirmed on” by the first timer a second timer is started. If you exit from the small area before that this timer has expired the light will be turned off. This second timer avoids that the light remains on when, for example, you pass near the house (inside the small area) without to stop at the house. If you remains in the small area the script will continue to run to check when you will go away from home just to reset at the condition where it checks when you area arriving to home. The reset happens when you will be out of the “large area + a gap distance”. Large area + gap distance define the gap area. The gap area is to avoid that the script switches exactly on large area border when you are going away from home. Infact it could be that the road you are on goes in and out from the large area or that the FIBARO GPS reports different values (greater or less than large area radius) when you are next to the large area border. So, without the gap area the script could turn on the light when you are going away from home. It is important to note that even though the script should erroneously turned on the light when you are going away from home the light will be turned off after the first timer is expired since you will not enter in the small area. Anyway the gap area avoids this kind of error and it is used only when you are going away from home. Link for script (ZIP file) and documentation (PDF) download: http://domotica.gposta.it
  9. KeyCode LUA program for a Digital Key with Fibaro UBS. KeyCode is a LUA script to create a digital key operated by a secret code. Requirements: Fibaro Universal Binary Sensor (UBS). one or two momentary switches (push buttons). Fibaro HC2. It permits to define: - two secret codes (one for each UBS input) - maximum number of failures - captive interval during which also the valid code will be recognized as invalid Two momentary keys can be used as keyboard to input the secret codes to open/close a door, arm/disarm alarms, turn on/off lights, etc... How it works. Input1 and/or Input2 of the UBS are configured to activate scenes. By pressing one, two or three times a momentary switch (key1, key2) connected to such inputs a digit (1, 2 or 3) is entered. A sequence of such digits is a code (secret code) that can be used to control devices, arm/disarm sensors/house alarm, activate scenes. The script permits to define secret codes of any length (any number of digits), composed only by the numbers 1, 2 or 3. Each digit of the code can be assigned to one of the keys (UBS inputs). It is possible to use only one UBS input or both the UBS inputs. For example, the code 2, 1, 3, 3, 1 corresponds to the following sequence: double click, one click, triple click, triple click, one click, of the key (momentary switch) to which the digit is assigned (digit to key assignment is described below). To confirm the code it needs to hold down one of the keys. The maximum interval between each digit or code confirmation sent to the script is configurable. Optionally it is possible to define the maximum number of consecutive code failures before to start a captive status interval during which also the right code will be refused as invalid. A code failure happens when the code confirmation is received (switch holding down) and the entered code doesn’t match the secret code. By one UBS and this script it is possible to manage a maximum of two secret codes, typically one code could be for activate a function (for example, arm a sensor) the other one to deactivate the function. You can download the script (ZIP file) and the documentation (PDF) here: http://domotica.gposta.it
  10. NightAndDay is a LUA script to set two global variables at sunrise and sunset and at sunrise + a sunrise offset and at sunset + a sunset offset. You can choose the name of the global variables to set. Default are itIsNight and itIsNightOne. You can define two different offset values (between -7200 and 7200 seconds) for both sunrise and sunset, sunrisetime_offset and sunsettime_offset. itIsNight will switch from 1 to 0 at sunrisetime and from 0 to 1 at sunsettime. itIsNightOne will switch from 1 to 0 at sunrisetime+sunrisetime_offset and from 0 to 1 at sunsettime+sunsettime_offset. At this link you can donwload the script (zip file) and the documentation (PDF): http://domotica.gposta.it
  11. as there was question in polish forum, http://forum.fibaro.com/index.php?/topic/20519-powiadomienie-e-mail/#entry80992here my solutions: to change email notification on low battery level, one can call this here (where 288 is my device) --[[ %% properties %% events %% globals --]] function setNoNotification(deviceId) local dev = api.get('/devices/' .. deviceId) dev.properties.batteryLowNotification = false api.put('/devices/' .. deviceId, dev) end setNoNotification(288) to change notification for all battery powered devices (only valid devices and sorted to rooms) one can call this here --[[ %% properties %% events %% globals --]] -- change to true or false, depends on needs local notification = false local devices = api.get('/devices') for _, dev in ipairs(devices) do local room = fibaro:getRoomNameByDeviceID(dev.id) -- do not change unassigned modules if not(room == "unassigned") then -- change only batt powered modules if (dev.properties.batteryLevel ~= nil) then -- change only valid modules if (dev.properties.nodeId ~= nil) then dev.properties.batteryLowNotification = notification api.put('/devices/' .. dev.id, dev) fibaro:debug("changed module: " .. dev.name .. " with id: " .. dev.id.. " in room: " .. fibaro:getRoomNameByDeviceID(dev.id)) end end end end
  12. Beta release of 3.0.0 News: All settings for phoneID, forecast times and what push to use in one table smartphoneID_and_fcst ={{281, "06:30", "17:00", "Telegram"},{32, "08:00", "17:00", "Fibaro"}} Report all errors you find --[[ %% autostart %% properties %% globals --]] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- HOWTO -- -- 1. Create a virtual device with 9 labels and set the ID to like below, else this scene will not work. -- 2. lblTemp, lblHum, lblBar, lblWind, lblRain, lblFcst, lblStation, lblUpdate, lblNotify -- 3. Change ID of virtual device in WU.selfId -- FIRST TIME USERS NEEDS TO COPY ALL CODE TO SCENE, after version 2.5.0 it should only be neccessary to update from "UPDATE FROM HERE" text -- NOTE -- -- Scheduled time you set for forecast push is just an indication of time. -- Real time will be the hour you set + minute of when scene starts. -- Script will check server version for new updated version (default = true) -- WU WeatherData - Fetch weather data from wunderground.com. Multilanguage support! -- Inspired by GEA(steven), stevenvd, Krikroff and many other users. -- Source - forum.fibaro.com, domotique-fibaro.fr and worldwideweb -- Special thanks to petergebruers from forum.fibaro.com with demo script -- -- -- PWS = Personal Weather Station -- LOCID = Public station -- -- -- 2014-03-22 - Permissions granted from Krikroff -- 2014-03-23 - Added rain and forecast, Added FR language. -- 2014-03-23 - Language variable changed to get the translation from wunderground.com in forcast -- 2014-03-24 - Added PL language -- 2014-03-24 - Select between PWS or LOCID to download weather data -- 2015-10-23 - New source code. -- 2015-10-23 - Added NL translation -- 2015-11-16 - Added DE, FR translation. Fixed some bug in the code(hardcoded smartphoneID,inch to metric for rain value) -- 2015-11-18 - Script moved to scene instead of mainloop in VD. VD is only used as GUI. -- 2015-11-18 - Send push if script cannot fetch data -- 2015-11-26 - adjustment of code. Function from sebcbien at domotique-fibaro.fr -- 2015-11-27 - Oops! Removed forecast push by mistace. -- 2016-02-11 - send push if new version of script is out -- 2016-03-31 - Added NO translation, did cleanup the code a little bit. -- 2016-03-31 - It is now posible to use Telegram as push. Change WU.pushOption value to Telegram or Fibaro. -- - also change WU.Telegramtoken and WU.Telegramchat_id to your values -- 2016-04-01 - Fixed bug when using Telegram push, forecast must send with lowercases. -- 2016-05-26 - Added support for multiple smartphone id when sending push -- 2016-05-30 - Implemented "UPDATE SECTION" -- 2016-07-13 - Bug fixed some code for sendPush to fibaro app -- 2016-07-14 - Telegram, possible to have forecast pushed to 2 different chat_id's -- 2016-07-15 - Save all importent values to variable. -- 2016-07-15 - Added RO, GR, PT, RU and CZ translation -- 2016-07-16 - Possible to have different time for push to all smartphones -- 2016.07-17 - Bugfixes. Changed layout of JSON table for smartphoneID, time and push option version = "{3.0.0}" WU = {} versionCheck = true -- check if new version of script exist on server WU.language = "SW"; -- EN, FR, SW, PL, NL, DE, NO, RO, CZ, GR, PT, RU (default is en) -- WU settings WU.APIkey = "14eaxxxxxxxxxxx" -- Put your WU api key here WU.PWS = "IGVLEBOR5" -- The PWS location to get data for (Personal Weather Station) WU.LOCID = "SWXX0076" -- The location ID to get data for (City location) WU.station = "PWS" -- PWS or LOCID ---- UPDATE FROM HERE ---- -- Other settings smartphoneID_and_fcst ={{281, "06:30", "17:00", "Telegram"},{32, "08:00", "17:00", "Fibaro"}} -- ID, time for morning and afternoon forecast and what push to use WU.sendPush = true -- send forecast with push -- Telegram settings -- IMPORTANT -- -- Telegramtoken needs to splitted into 2 parts. First part1 is before the ":", part2 is after the ":" WU.Telegramtoken1_part1 = "187xxxxxx" WU.Telegramtoken1_part2 = "AAHfzhTcsKloviNxxxxxxxxxxxxxxxxx" WU.Telegramchat_id1 = "2025xxxxx" -- If you want forecast to be pushed to a second phone WU.dualChat_ID = false -- set to true if more then 1 smartphone that should have forecast pushed. WU.Telegramtoken2_part1 = "187xxxxxx" WU.Telegramtoken2_part2 = "AAHfzhTcsKloviNxxxxxxxxxxxxxxxxx" WU.Telegramchat_id2 = "2025xxxxx" updateEvery = 5 -- get data every xx minutes WU.selfId = 150 -- ID of virtual device ---- UPDATE FROM HERE ---- -- Read settings from variable if not(fibaro:getGlobal("WUAPI") == nil) and (fibaro:getGlobal("Telegramtoken_part1") == nil) and (fibaro:getGlobal("Telegramtoken_part2") == nil) and (fibaro:getGlobal("Telegramchat_id") == nil) and (fibaro:getGlobal("Telegramchat_id2") == nil ) then WU.APIkey = fibaro:getGlobal("WUAPI") WU.Telegramtoken1 = fibaro:getGlobal("Telegramtoken1_part1")..":"..fibaro:getGlobal("Telegramtoken1_part2") WU.Telegramchat_id1 = fibaro:getGlobal("Telegramchat_id1") WU.Telegramurl1 = "https://api.telegram.org/bot"..WU.Telegramtoken1.."/sendMessage?chat_id="..WU.Telegramchat_id1.."&text=" if WU.dualChat_ID then WU.Telegramtoken2 = fibaro:getGlobal("Telegramtoken2_part1")..":" fibaro:getGlobal("Telegramtoken2_part2") WU.Telegramchat_id2 = fibaro:getGlobal("Telegramchat_id2") WU.Telegramurl2 = "https://api.telegram.org/bot"..WU.Telegramtoken2.."/sendMessage?chat_id="..WU.Telegramchat_id2.."&text=" end end -- End read settings from variable WU.translation = {true} WU.currentDate = os.date("*t"); DoNotRecheckBefore = os.time() WU.scheduler = os.time()+60*updateEvery WU.translation["EN"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push forecast", Temperature = "Temperature", Humidity = "Humidity", Pressure = "Pressure", Wind = "Wind", Rain = "Rain", Forecast = "Forecast", Station = "Station", Fetched = "Fetched", Data_processed = "Data processed", Update_interval = "Next update will be in (min)", No_data_fetched = "No data fetched", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", NO_STATIONID_FOUND = "No stationID found", NO_DATA_FOUND = "No data found" } WU.translation["FR"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push prévisions", Temperature = "Température", Humidity = "Humidité", Pressure = "Pression", Wind = "Vent", Rain = "Pluie", Forecast = "Prévisions", Station = "Station", Fetched = "Reçu", Data_processed = "Données Analysées", Update_interval = "Prochaine update prévue dans (min)", No_data_fetched = "Pas de données reçues", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", NO_STATIONID_FOUND = "StationID non trouvée", NO_DATA_FOUND = "Pas de données disponibles" } WU.translation["SW"] = { Exiting_loop_push = "Push loop avslutad", Push_forecast = "Push forecast", Temperature = "Temperatur", Humidity = "Fuktighet", Pressure = "Barometer", Wind = "Vind", Rain = "Regn", Forecast = "Prognos", Station = "Station", Fetched = "Hämtat", Data_processed = "All data processat", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", Update_interval = "Nästa uppdatering är om (min)", No_data_fetched = "Inget data hämtat", NO_STATIONID_FOUND = "StationID ej funnet", NO_DATA_FOUND = "Ingen data hos WU" } WU.translation["PL"] = { Exiting_loop_push = "Kończę pętlę PUSH", Push_forecast = "PUSH prognozy", Temperature = "Temperatura", Humidity = "Wilgotność", Pressure = "Ciśnienie", Wind = "Wiatr", Rain = "Deszcz", Forecast = "Prognoza", Station = "Stacja", Fetched = "Nie pobrano danych", Data_processed = "Dane przetworzone", new_version = "Dostępna nowa wersja skryptu WUWeather.lua ! ", script_url = "http://jonnylarsson.se/JL/", No_data_fetched = "Brak danych", Update_interval = "Następna aktualizacja za (min)", NO_STATIONID_FOUND = "Nie znaleziono ID Stacji", NO_DATA_FOUND = "Brak danych" } WU.translation["NL"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push verwachting", Temperature = "Temperatuur", Humidity = "Vochtigheid", Pressure = "Druk", Wind = "Wind", Rain = "Regen", Forecast = "Verwachting", Station = "Weerstation", Fetched = "Ontvangen", Data_processed = "Gegevens verwerkt", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", Update_interval = "Volgende update in (min)", No_data_fetched = "Geen gegevens ontvangen", NO_STATIONID_FOUND = "Geen stationID gevonden", NO_DATA_FOUND = "Geen gegevens gevonden" } WU.translation["DE"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push vorhersage", Temperature = "Temperatur", Humidity = "Luftfeuchtigkeit", Pressure = "Luftdruck", Wind = "Wind", Rain = "Regen", Forecast = "Vorhersage", Station = "Station", Fetched = "Abgerufen", Data_processed = "Daten verarbeitet", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", No_data_fetched = "Keine Daten abgerufen", Update_interval = "Das nächste Update in (min)", NO_STATIONID_FOUND = "Keine stationID gefunden", NO_DATA_FOUND = "Keine Daten gefunden" } WU.translation["NO"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push værmelding", Temperature = "Temperatur", Humidity = "Fuktighet", Pressure = "Barometer", Wind = "Vind", Rain = "Regn", Forecast = "Prognose", Station = "Stasjon", Fetched = "Hentet", Data_processed = "All data prosessert", Update_interval = "Neste oppdatering om (min)", No_data_fetched = "Ingen data hentet", NO_STATIONID_FOUND = "StasjonID ikke funnet", NO_DATA_FOUND = "Ingen data hos WU" } WU.translation["CZ"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push forecast", Temperature = "Teplota", Humidity = "Vlhkost", Pressure = "(Atmosférický) Tlak", Wind = "Vítr", Rain = "Déšť ", Forecast = "Předpověď", Station = "Stanice", Fetched = "Předána", Data_processed = "Data_zpracována", Update_interval = "Časová_prodleva_mezi_aktualizacemi", No_data_fetched = "Data_nebyla_předána", NO_STATIONID_FOUND = "Stanice_nenalezena", NO_DATA_FOUND = "Data_Nenalezena" } WU.translation["RO"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Prognoza apăsare", Temperature = "Temperatura", Humidity = "Umiditate", Pressure = "Presiune", Wind = "Vant", Rain = "Ploaie", Forecast = "Prognoza", Station = "Statie", Fetched = "Preluat", Data_processed = "Datele prelucrate", Update_interval = "Urmatorul update va fi in (min)", No_data_fetched = "Nu exista date preluate", NO_STATIONID_FOUND = "Nu a fost gasit stationID ", NO_DATA_FOUND = "Datele nu au fost gasite" } WU.translation["GR"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Πρόγνωση push", Temperature = "Θερμοκρασία", Humidity = "Υγρασία", Pressure = "Πίεση", Wind = "Άνεμος", Rain = "Βροχή", Forecast = "Πρόβλεψη", Station = "Σταθμός", Fetched = "Παραλήφθηκαν", Data_processed = "Επεξεργασμένα δεδομένα", Update_interval = "Η επόμενη ενημέρωση θα γίνει σε (min)", No_data_fetched = "Δεν παραλήφθηκαν δεδομένα", NO_STATIONID_FOUND = "Δεν βρέθηκε το Station ID", NO_DATA_FOUND = "Δεν βρέθηκαν δεδομένα" } WU.translation["PT"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Previsão do impulso", Temperature = "Temperatura", Humidity = "Humidade", Pressure = "Pressão", Wind = "Vento", Rain = "Chuva", Forecast = "Previsão", Station = "Estação", Fetched = "Procurar", Data_processed = "Dados processados", Update_interval = "Próxima atualização será em (min)", No_data_fetched = "Não foram encontrados dados", NO_STATIONID_FOUND = "Não foi detetada nenhuma estação", NO_DATA_FOUND = "Não foram encontrados dados" } WU.translation["RU"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Прогноз Нажмите", Temperature = "Температура", Humidity = "Влажность", Pressure = "Давление", Wind = "Ветер", Rain = "Дождь", Forecast = "Прогноз", Station = "Станция", Fetched = "Получено", Data_processed = "Данные обработаны", Update_interval = "Следующее обновление через (мин.)", No_data_fetched = "Данные не получены", NO_STATIONID_FOUND = "Данная станция не найдена", NO_DATA_FOUND = "Данные не найдены" } if WU.station == "LOCID" then locationID = WU.LOCID elseif WU.station == "PWS" then locationID = WU.PWS end Debug = function ( color, message ) fibaro:debug(string.format('<%s style="color:%s;">%s</%s>', "span", color, message, "span")); end function log(str) if debug then fibaro:debug(str); end end function errorlog(str) fibaro:debug("<font color='red'>"..str.."</font>") end function Telegrambot(msg) local selfhttp = net.HTTPClient({timeout=2000}) url = WU.Telegramurl1 .. msg selfhttp:request(url, { options={ headers = selfhttp.controlHeaders, data = requestBody, method = 'GET' }, success = function(status) local result = json.decode(status.data); if result.ok == true then Debug("grey", "Sucessfully sent message to Telegram Bot...") else --errorlog("failed"); print(status.data); end end, error = function(error) --errorlog("ERROR") Debug("red", error) end }) if WU.dualChat_ID then url2 = WU.Telegramurl2 .. msg selfhttp:request(url2, { options={ headers = selfhttp.controlHeaders, data = requestBody, method = 'GET' }, success = function(status) local result = json.decode(status.data); if result.ok == true then Debug("grey", "Sucessfully sent message to Telegram Bot...") else --errorlog("failed"); print(status.data); end end, error = function(error) --errorlog("ERROR") Debug("red", error) end }) end end function versionChecker() local function getMethod(requestUrl, successCallback, errorCallback) local http = net.HTTPClient() http:request(requestUrl, { options = { method = 'GET', headers = { }, }, success = successCallback, error = errorCallback }) end content = "WUWeather.lua" local url = 'http://jonnylarsson.se/JL/'..content getMethod(url, function(resp) s = resp.data serverVersion = string.match(s, "{(.-)}"); scriptVersion = string.match(version, "{(.-)}"); if serverVersion > scriptVersion then Debug("grey", "Checking script version...") Debug("yellow", "There is a new version out! "..'<a href="http://jonnylarsson.se/JL/WUWeather.lua" target="_blank" style="display:inline;color:Cyan">Get it!</a>') if WU.sendPush then if WU.pushOption == "Fibaro" then fibaro:call(WU.smartphoneID , "sendPush", WU.translation[WU.language]["new_version"].." "..WU.translation[WU.language]["script_url"]) elseif WU.pushOption == "Telegram" then Telegrambot(WU.translation[WU.language]["new_version"].." "..WU.translation[WU.language]["script_url"]) end end end end, function(err) print('error' .. err) end ) end local http = net.HTTPClient() local function errorWU(err) if WU.pushOption == "Fibaro" then fibaro:call(WU.smartphoneID , "sendPush", "[WUWeather scene]. Error: "..err ) elseif WU.pushOption == "Telegram" then Telegrambot("[WUWeather scene]. Error: "..err ) end Debug( "red", "[HTTPClient:request]. Error: "..err ); end local function sendPopup() -- variable containing path of Motion Sensor’s icon local imgUrl = popupIMG -- pop-up call HomeCenter.PopupService.publish({ -- title (required) title = 'Weather forecast', -- subtitle(optional), e.g. time and date of the pop-up call subtitle = os.date("%I:%M:%S %p | %B %d, %Y"), -- content header (optional) contentTitle = 'Forecast from WU Weather', -- content (required) contentBody = fcastday.." - "..fcast, -- notification image (assigned from the variable) img = imgUrl, -- type of the pop-up type = 'Info', }) end function createGlobalIfNotExists(varName, defaultValue) if (fibaro:getGlobal(varName) == nil) then Debug("cyan", "Creating the variable: "..varName.." with value: "..defaultValue) newVar = {} newVar.name = varName newVar.value = defaultValue local http = net.HTTPClient() http:request("http://127.0.0.1:11111/api/globalVariables", { options = { method = 'POST', data = json.encode(newVar)}}) end end local function processWU(response) http:request("http://api.wunderground.com/api/"..WU.APIkey.."/conditions/forecast/lang:"..WU.language.."/q/"..WU.station..":"..locationID..".json",{ options = {method = 'GET'}, success = processWU, error = errorWU }) Debug( "green", "Now downloading data from www.wunderground.com"); if response then -- the first time you enter the loop, this will be nil if response.status~=200 then Debug( "red", "Server returned an error, but will retry. Error: "..response.status) else WU.now = os.date("%H:%M") jsonTable = json.decode(response.data) stationID = jsonTable.current_observation.station_id city = jsonTable.current_observation.observation_location.city humidity = jsonTable.current_observation.relative_humidity temperature = jsonTable.current_observation.temp_c pression = jsonTable.current_observation.pressure_mb wind = jsonTable.current_observation.wind_kph rain = jsonTable.current_observation.precip_today_metric icon = jsonTable.current_observation.icon weathericon = jsonTable.current_observation.icon_url fcstday1 = jsonTable.forecast.txt_forecast.forecastday[1].title fcst1 = jsonTable.forecast.txt_forecast.forecastday[1].fcttext_metric fcst1icon = jsonTable.forecast.txt_forecast.forecastday[1].icon_url fcstday2 = jsonTable.forecast.txt_forecast.forecastday[2].title fcst2 = jsonTable.forecast.txt_forecast.forecastday[2].fcttext_metric fcst2icon = jsonTable.forecast.txt_forecast.forecastday[2].icon_url fcst1_mobile = jsonTable.forecast.simpleforecast.forecastday[1].conditions fcst2_mobile = jsonTable.forecast.simpleforecast.forecastday[2].conditions if (stationID ~= nil) then fibaro:call(WU.selfId , "setProperty", "ui.lblStation.value", locationID); fibaro:call(WU.selfId , "setProperty", "ui.lblCity.value", city); fibaro:call(WU.selfId , "setProperty", "ui.lblTemp.value", WU.translation[WU.language]["Temperature"].." "..temperature.." °C"); fibaro:call(WU.selfId , "setProperty", "ui.lblHum.value", WU.translation[WU.language]["Humidity"].." "..humidity); fibaro:call(WU.selfId , "setProperty", "ui.lblBar.value", WU.translation[WU.language]["Pressure"].." "..pression.." mb"); fibaro:call(WU.selfId , "setProperty", "ui.lblWind.value", WU.translation[WU.language]["Wind"].." "..wind.." km/h"); fibaro:call(WU.selfId , "setProperty", "ui.lblRain.value", WU.translation[WU.language]["Rain"].." "..rain.." mm"); if (WU.now >= "03:00" and WU.now <= "15:59") then fibaro:call(WU.selfId , "setProperty", "ui.lblFcst.value",WU.translation[WU.language]["Forecast"].." "..fcstday1.." - "..fcst1_mobile); --fibaro:call(WU.selfId , "setProperty", "ui.lblIcon.value","<img src=http://jonnylarsson.se/JL/png/"..icon..".png>"); elseif (WU.now >= "16:00" and WU.now <= "23:59") then --fibaro:call(WU.selfId , "setProperty", "ui.lblIcon.value","<img src=http://jonnylarsson.se/JL/png/nt_"..icon..".png>"); fibaro:call(WU.selfId , "setProperty", "ui.lblFcst.value", WU.translation[WU.language]["Forecast"].." "..fcstday2.." - "..fcst2_mobile); end if WU.sendPush then for k,smartphoneID_and_fcst in ipairs(smartphoneID_and_fcst) do if (os.date("%H:%M") == smartphoneID_and_fcst[2]) then if versionCheck then versionChecker() end if smartphoneID_and_fcst[4] == "Fibaro" then fcastday = fcstday1 fcast = fcst1 fibaro:call(smartphoneID_and_fcst[1], "sendPush", fcstday1.." - "..fcst1) popupIMG = "http://jonnylarsson.se/JL/png/"..icon..".png" sendPopup() Debug("grey", "Sucessfully sent push message to "..smartphoneID_and_fcst[1]) elseif smartphoneID_and_fcst[4] == "Telegram" then Telegrambot(fcstday1.." - "..string.lower(fcst1).." - "..fcst1icon) elseif smartphoneID_and_fcst[4] == "Pushover" then Pushover('fcstday1.." - "..string.lower(fcst1).." - "..fcst1icon') end end end for k,smartphoneID_and_fcst in ipairs(smartphoneID_and_fcst) do if (os.date("%H:%M") == smartphoneID_and_fcst[3]) then if smartphoneID_and_fcst[4] == "Fibaro" then fcastday = fcstday2 fcast = fcst2 fibaro:call(smartphoneID_and_fcst[1] , "sendPush", fcstday2.." - "..fcst2) popupIMG = "http://jonnylarsson.se/JL/png/nt_"..icon..".png" sendPopup() Debug("grey", "Sucessfully sent push message to "..smartphoneID_and_fcst[1]) elseif smartphoneID_and_fcst[4] == "Telegram" then Telegrambot(fcstday2.." - "..string.lower(fcst2).." - "..fcst2icon) elseif smartphoneID_and_fcst[4] == "Pushover" then Pushover("Test message") end end end end if WU.sendPush then fibaro:call(WU.selfId , "setProperty", "ui.lblNotify.value", WU.translation[WU.language]["Push_forecast"].." = true"); else fibaro:call(WU.selfId , "setProperty", "ui.lblNotify.value",WU.translation[WU.language]["Push_forecast"].." = false"); end WU.scheduler = os.time()+updateEvery*60 fibaro:call(WU.selfId, "setProperty", "ui.lblUpdate.value", os.date("%c")); fibaro:debug(WU.translation[WU.language]["Data_processed"]) fibaro:debug(WU.translation[WU.language]["Update_interval"].." "..updateEvery) else fibaro:debug(WU.translation[WU.language]["NO_STATIONID_FOUND"]) end end sleepAndcheck = 0 while sleepAndcheck <= 20*updateEvery do fibaro:sleep(3000) sleepAndcheck = sleepAndcheck+1 for k,smartphoneID_and_fcst in ipairs(smartphoneID_and_fcst) do if (DoNotRecheckBefore <= os.time()) and ((WU.scheduler == os.time) or (os.date("%H:%M") == smartphoneID_and_fcst[2]) or (os.date("%H:%M") == smartphoneID_and_fcst[3])) then fibaro:debug(WU.translation[WU.language]["Push_forecast"]) Debug("orange", WU.translation[WU.language]["Exiting_loop_push"]); DoNotRecheckBefore = os.time()+60 sleepAndcheck = 20*updateEvery end end end end end Debug( "orange", "WU Weather - LUA Scripting by Jonny Larsson 2015/2016" ); Debug( "orange", "Version: "..version); if versionCheck then versionChecker() end createGlobalIfNotExists("WUAPI", WU.APIkey) createGlobalIfNotExists("Telegramtoken1_part1", WU.Telegramtoken1_part1) createGlobalIfNotExists("Telegramtoken1_part2", WU.Telegramtoken1_part2) createGlobalIfNotExists("Telegramchat_id1", WU.Telegramchat_id1) if WU.dualChat_ID then createGlobalIfNotExists("Telegramtoken2_part1", WU.Telegramtoken2_part1) createGlobalIfNotExists("Telegramtoken2_part2", WU.Telegramtoken2_part2) createGlobalIfNotExists("Telegramchat_id2", WU.Telegramchat_id2) end for k,smartphoneID_and_fcst in ipairs(smartphoneID_and_fcst) do Debug( "yellow", "Morning forecast push will be for ID: "..smartphoneID_and_fcst[1].." @ "..smartphoneID_and_fcst[2].." with "..smartphoneID_and_fcst[4]); Debug( "yellow", "Afternoon forecast push will be for ID: "..smartphoneID_and_fcst[1].." @ "..smartphoneID_and_fcst[3].." with "..smartphoneID_and_fcst[4]); end processWU() --this starts an endless loop, until an error occurs ---- END OF UPDATE ----
  13. Another update, this update can handle individual time for each smartphones when sending push. Example smartphoneID_and_fcstAM ={{281, "06:30"},{32, "08:00"}} -- ID and time to send morning forecast smartphoneID_and_fcstPM ={{281, "17:00"},{32, "17:00"}} -- ID and time to send afternoon forecast ID 281 will get morning forecast at 06:30 and ID 32 will get it at 08:00 (same options for afternoon forecast. Can handle more then 2 smartphones, just fill in how many you like Complete code --[[ %% autostart %% properties %% globals --]] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- HOWTO -- -- 1. Create a virtual device with 9 labels and set the ID to like below, else this scene will not work. -- 2. lblTemp, lblHum, lblBar, lblWind, lblRain, lblFcst, lblStation, lblUpdate, lblNotify -- 3. Change ID of virtual device in WU.selfId -- FIRST TIME USERS NEEDS TO COPY ALL CODE TO SCENE, after version 2.5.0 it should only be neccessary to update from "UPDATE FROM HERE" text -- NOTE -- -- Scheduled time you set for forecast push is just an indication of time. -- Real time will be the hour you set + minute of when scene starts. -- Script will check server version for new updated version (default = true) -- WU WeatherData - Fetch weather data from wunderground.com. Multilanguage support! -- Inspired by GEA(steven), stevenvd, Krikroff and many other users. -- Source - forum.fibaro.com, domotique-fibaro.fr and worldwideweb -- Special thanks to petergebruers from forum.fibaro.com with demo script -- -- -- PWS = Personal Weather Station -- LOCID = Public station -- -- -- 2014-03-22 - Permissions granted from Krikroff -- 2014-03-23 - Added rain and forecast, Added FR language. -- 2014-03-23 - Language variable changed to get the translation from wunderground.com in forcast -- 2014-03-24 - Added PL language -- 2014-03-24 - Select between PWS or LOCID to download weather data -- 2015-10-23 - New source code. -- 2015-10-23 - Added NL translation -- 2015-11-16 - Added DE, FR translation. Fixed some bug in the code(hardcoded smartphoneID,inch to metric for rain value) -- 2015-11-18 - Script moved to scene instead of mainloop in VD. VD is only used as GUI. -- 2015-11-18 - Send push if script cannot fetch data -- 2015-11-26 - adjustment of code. Function from sebcbien at domotique-fibaro.fr -- 2015-11-27 - Oops! Removed forecast push by mistace. -- 2016-02-11 - send push if new version of script is out -- 2016-03-31 - Added NO translation, did cleanup the code a little bit. -- 2016-03-31 - It is now posible to use Telegram as push. Change WU.pushOption value to Telegram or Fibaro. -- - also change WU.Telegramtoken and WU.Telegramchat_id to your values -- 2016-04-01 - Fixed bug when using Telegram push, forecast must send with lowercases. -- 2016-05-26 - Added support for multiple smartphone id when sending push -- 2016-05-30 - Implemented "UPDATE SECTION" -- 2016-07-13 - Bug fixed some code for sendPush to fibaro app -- 2016-07-14 - Telegram, possible to have forecast pushed to 2 different chat_id's -- 2016-07-15 - Save all importent values to variable. -- 2016-07-15 - Added RO, GR, PT, RU and CZ translation -- 2016-07-16 - Possible to have different time for push to all smartphones version = "{2.6.0}" WU = {} versionCheck = true -- check if new version of script exist on server WU.language = "SW"; -- EN, FR, SW, PL, NL, DE, NO, RO, CZ, GR, PT, RU (default is en) -- WU settings WU.APIkey = "14eaxxxxxxxxxxx" -- Put your WU api key here WU.PWS = "IGVLEBOR5" -- The PWS location to get data for (Personal Weather Station) WU.LOCID = "SWXX0076" -- The location ID to get data for (City location) WU.station = "PWS" -- PWS or LOCID ---- UPDATE FROM HERE ---- -- Other settings smartphoneID_and_fcstAM ={{281, "06:30"},{32, "08:00"}} -- ID and time to send morning forecast smartphoneID_and_fcstPM ={{281, "17:00"},{32, "17:00"}} -- ID and time to send afternoon forecast WU.sendPush = true -- send forecast with push WU.pushOption = "Fibaro" -- Use Fibaro or Telegram? -- Telegram settings -- IMPORTANT -- -- Telegramtoken needs to splitted into 2 parts. First part1 is before the ":", part2 is after the ":" WU.Telegramtoken1_part1 = "187xxxxxx" WU.Telegramtoken1_part2 = "AAHfzhTcsKloviNxxxxxxxxxxxxxxxxx" WU.Telegramchat_id1 = "2025xxxxx" -- If you want forecast to be pushed to a second phone WU.dualChat_ID = false -- set to true if more then 1 smartphone that should have forecast pushed. WU.Telegramtoken2_part1 = "187xxxxxx" WU.Telegramtoken2_part2 = "AAHfzhTcsKloviNxxxxxxxxxxxxxxxxx" WU.Telegramchat_id2 = "2025xxxxx" updateEvery = 1 -- get data every xx minutes WU.selfId = 150 -- ID of virtual device ---- UPDATE FROM HERE ---- -- Read settings from variable if not(fibaro:getGlobal("WUAPI") == nil) and (fibaro:getGlobal("Telegramtoken_part1") == nil) and (fibaro:getGlobal("Telegramtoken_part2") == nil) and (fibaro:getGlobal("Telegramchat_id") == nil) and (fibaro:getGlobal("Telegramchat_id2") == nil ) then WU.APIkey = fibaro:getGlobal("WUAPI") WU.Telegramtoken1 = fibaro:getGlobal("Telegramtoken1_part1")..":"..fibaro:getGlobal("Telegramtoken1_part2") WU.Telegramchat_id1 = fibaro:getGlobal("Telegramchat_id1") WU.Telegramurl1 = "https://api.telegram.org/bot"..WU.Telegramtoken1.."/sendMessage?chat_id="..WU.Telegramchat_id1.."&text=" if WU.dualChat_ID then WU.Telegramtoken2 = fibaro:getGlobal("Telegramtoken2_part1")..":" fibaro:getGlobal("Telegramtoken2_part2") WU.Telegramchat_id2 = fibaro:getGlobal("Telegramchat_id2") WU.Telegramurl2 = "https://api.telegram.org/bot"..WU.Telegramtoken2.."/sendMessage?chat_id="..WU.Telegramchat_id2.."&text=" end end -- End read settings from variable WU.translation = {true} WU.currentDate = os.date("*t"); DoNotRecheckBefore = os.time() WU.scheduler = os.time()+60*updateEvery WU.translation["EN"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push forecast", Temperature = "Temperature", Humidity = "Humidity", Pressure = "Pressure", Wind = "Wind", Rain = "Rain", Forecast = "Forecast", Station = "Station", Fetched = "Fetched", Data_processed = "Data processed", Update_interval = "Next update will be in (min)", No_data_fetched = "No data fetched", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", NO_STATIONID_FOUND = "No stationID found", NO_DATA_FOUND = "No data found" } WU.translation["FR"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push prévisions", Temperature = "Température", Humidity = "Humidité", Pressure = "Pression", Wind = "Vent", Rain = "Pluie", Forecast = "Prévisions", Station = "Station", Fetched = "Reçu", Data_processed = "Données Analysées", Update_interval = "Prochaine update prévue dans (min)", No_data_fetched = "Pas de données reçues", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", NO_STATIONID_FOUND = "StationID non trouvée", NO_DATA_FOUND = "Pas de données disponibles" } WU.translation["SW"] = { Exiting_loop_push = "Push loop avslutad", Push_forecast = "Push forecast", Temperature = "Temperatur", Humidity = "Fuktighet", Pressure = "Barometer", Wind = "Vind", Rain = "Regn", Forecast = "Prognos", Station = "Station", Fetched = "Hämtat", Data_processed = "All data processat", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", Update_interval = "Nästa uppdatering är om (min)", No_data_fetched = "Inget data hämtat", NO_STATIONID_FOUND = "StationID ej funnet", NO_DATA_FOUND = "Ingen data hos WU" } WU.translation["PL"] = { Exiting_loop_push = "Kończę pętlę PUSH", Push_forecast = "PUSH prognozy", Temperature = "Temperatura", Humidity = "Wilgotność", Pressure = "Ciśnienie", Wind = "Wiatr", Rain = "Deszcz", Forecast = "Prognoza", Station = "Stacja", Fetched = "Nie pobrano danych", Data_processed = "Dane przetworzone", new_version = "Dostępna nowa wersja skryptu WUWeather.lua ! ", script_url = "http://jonnylarsson.se/JL/", No_data_fetched = "Brak danych", Update_interval = "Następna aktualizacja za (min)", NO_STATIONID_FOUND = "Nie znaleziono ID Stacji", NO_DATA_FOUND = "Brak danych" } WU.translation["NL"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push verwachting", Temperature = "Temperatuur", Humidity = "Vochtigheid", Pressure = "Druk", Wind = "Wind", Rain = "Regen", Forecast = "Verwachting", Station = "Weerstation", Fetched = "Ontvangen", Data_processed = "Gegevens verwerkt", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", Update_interval = "Volgende update in (min)", No_data_fetched = "Geen gegevens ontvangen", NO_STATIONID_FOUND = "Geen stationID gevonden", NO_DATA_FOUND = "Geen gegevens gevonden" } WU.translation["DE"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push vorhersage", Temperature = "Temperatur", Humidity = "Luftfeuchtigkeit", Pressure = "Luftdruck", Wind = "Wind", Rain = "Regen", Forecast = "Vorhersage", Station = "Station", Fetched = "Abgerufen", Data_processed = "Daten verarbeitet", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", No_data_fetched = "Keine Daten abgerufen", Update_interval = "Das nächste Update in (min)", NO_STATIONID_FOUND = "Keine stationID gefunden", NO_DATA_FOUND = "Keine Daten gefunden" } WU.translation["NO"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push værmelding", Temperature = "Temperatur", Humidity = "Fuktighet", Pressure = "Barometer", Wind = "Vind", Rain = "Regn", Forecast = "Prognose", Station = "Stasjon", Fetched = "Hentet", Data_processed = "All data prosessert", Update_interval = "Neste oppdatering om (min)", No_data_fetched = "Ingen data hentet", NO_STATIONID_FOUND = "StasjonID ikke funnet", NO_DATA_FOUND = "Ingen data hos WU" } WU.translation["CZ"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push forecast", Temperature = "Teplota", Humidity = "Vlhkost", Pressure = "(Atmosférický) Tlak", Wind = "Vítr", Rain = "Déšť ", Forecast = "Předpověď", Station = "Stanice", Fetched = "Předána", Data_processed = "Data_zpracována", Update_interval = "Časová_prodleva_mezi_aktualizacemi", No_data_fetched = "Data_nebyla_předána", NO_STATIONID_FOUND = "Stanice_nenalezena", NO_DATA_FOUND = "Data_Nenalezena" } WU.translation["RO"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Prognoza apăsare", Temperature = "Temperatura", Humidity = "Umiditate", Pressure = "Presiune", Wind = "Vant", Rain = "Ploaie", Forecast = "Prognoza", Station = "Statie", Fetched = "Preluat", Data_processed = "Datele prelucrate", Update_interval = "Urmatorul update va fi in (min)", No_data_fetched = "Nu exista date preluate", NO_STATIONID_FOUND = "Nu a fost gasit stationID ", NO_DATA_FOUND = "Datele nu au fost gasite" } WU.translation["GR"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Πρόγνωση push", Temperature = "Θερμοκρασία", Humidity = "Υγρασία", Pressure = "Πίεση", Wind = "Άνεμος", Rain = "Βροχή", Forecast = "Πρόβλεψη", Station = "Σταθμός", Fetched = "Παραλήφθηκαν", Data_processed = "Επεξεργασμένα δεδομένα", Update_interval = "Η επόμενη ενημέρωση θα γίνει σε (min)", No_data_fetched = "Δεν παραλήφθηκαν δεδομένα", NO_STATIONID_FOUND = "Δεν βρέθηκε το Station ID", NO_DATA_FOUND = "Δεν βρέθηκαν δεδομένα" } WU.translation["PT"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Previsão do impulso", Temperature = "Temperatura", Humidity = "Humidade", Pressure = "Pressão", Wind = "Vento", Rain = "Chuva", Forecast = "Previsão", Station = "Estação", Fetched = "Procurar", Data_processed = "Dados processados", Update_interval = "Próxima atualização será em (min)", No_data_fetched = "Não foram encontrados dados", NO_STATIONID_FOUND = "Não foi detetada nenhuma estação", NO_DATA_FOUND = "Não foram encontrados dados" } WU.translation["RU"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Прогноз Нажмите", Temperature = "Температура", Humidity = "Влажность", Pressure = "Давление", Wind = "Ветер", Rain = "Дождь", Forecast = "Прогноз", Station = "Станция", Fetched = "Получено", Data_processed = "Данные обработаны", Update_interval = "Следующее обновление через (мин.)", No_data_fetched = "Данные не получены", NO_STATIONID_FOUND = "Данная станция не найдена", NO_DATA_FOUND = "Данные не найдены" } if WU.station == "LOCID" then locationID = WU.LOCID elseif WU.station == "PWS" then locationID = WU.PWS end Debug = function ( color, message ) fibaro:debug(string.format('<%s style="color:%s;">%s</%s>', "span", color, message, "span")); end local function log(str) if debug then fibaro:debug(str); end; end local function errorlog(str) fibaro:debug("<font color='red'>"..str.."</font>"); end function Telegrambot(msg) local selfhttp = net.HTTPClient({timeout=2000}) url = WU.Telegramurl1 .. msg selfhttp:request(url, { options={ headers = selfhttp.controlHeaders, data = requestBody, method = 'GET' }, success = function(status) local result = json.decode(status.data); if result.ok == true then Debug("grey", "Sucessfully sent message to Telegram Bot...") else --errorlog("failed"); print(status.data); end end, error = function(error) --errorlog("ERROR") Debug("red", error) end }) if WU.dualChat_ID then url2 = WU.Telegramurl2 .. msg selfhttp:request(url2, { options={ headers = selfhttp.controlHeaders, data = requestBody, method = 'GET' }, success = function(status) local result = json.decode(status.data); if result.ok == true then Debug("grey", "Sucessfully sent message to Telegram Bot...") else --errorlog("failed"); print(status.data); end end, error = function(error) --errorlog("ERROR") Debug("red", error) end }) end end function versionChecker() local function getMethod(requestUrl, successCallback, errorCallback) local http = net.HTTPClient() http:request(requestUrl, { options = { method = 'GET', headers = { }, }, success = successCallback, error = errorCallback }) end content = "WUWeather.lua" local url = 'http://jonnylarsson.se/JL/'..content getMethod(url, function(resp) s = resp.data serverVersion = string.match(s, "{(.-)}"); scriptVersion = string.match(version, "{(.-)}"); if serverVersion > scriptVersion then Debug("grey", "Checking script version...") Debug("yellow", "There is a new version out! "..'<a href="http://jonnylarsson.se/JL/WUWeather.lua" target="_blank" style="display:inline;color:Cyan">Get it!</a>') if WU.sendPush then if WU.pushOption == "Fibaro" then fibaro:call(WU.smartphoneID , "sendPush", WU.translation[WU.language]["new_version"].." "..WU.translation[WU.language]["script_url"]) elseif WU.pushOption == "Telegram" then Telegrambot(WU.translation[WU.language]["new_version"].." "..WU.translation[WU.language]["script_url"]) end end end end, function(err) print('error' .. err) end ) end local http = net.HTTPClient() local function errorWU(err) if WU.pushOption == "Fibaro" then fibaro:call(WU.smartphoneID , "sendPush", "[WUWeather scene]. Error: "..err ) elseif WU.pushOption == "Telegram" then Telegrambot("[WUWeather scene]. Error: "..err ) end Debug( "red", "[HTTPClient:request]. Error: "..err ); end local function sendPopup() -- variable containing path of Motion Sensor’s icon local imgUrl = popupIMG -- pop-up call HomeCenter.PopupService.publish({ -- title (required) title = 'Weather forecast', -- subtitle(optional), e.g. time and date of the pop-up call subtitle = os.date("%I:%M:%S %p | %B %d, %Y"), -- content header (optional) contentTitle = 'Forecast from WU Weather', -- content (required) contentBody = fcastday.." - "..fcast, -- notification image (assigned from the variable) img = imgUrl, -- type of the pop-up type = 'Info', }) end function createGlobalIfNotExists(varName, defaultValue) if (fibaro:getGlobal(varName) == nil) then Debug("cyan", "Creating the variable: "..varName.." with value: "..defaultValue) newVar = {} newVar.name = varName newVar.value = defaultValue local http = net.HTTPClient() http:request("http://127.0.0.1:11111/api/globalVariables", { options = { method = 'POST', data = json.encode(newVar)}}) end end local function processWU(response) http:request("http://api.wunderground.com/api/"..WU.APIkey.."/conditions/forecast/lang:"..WU.language.."/q/"..WU.station..":"..locationID..".json",{ options = {method = 'GET'}, success = processWU, error = errorWU }) Debug( "green", "Now downloading data from www.wunderground.com"); if response then -- the first time you enter the loop, this will be nil if response.status~=200 then Debug( "red", "Server returned an error, but will retry. Error: "..response.status) else WU.now = os.date("%H:%M") jsonTable = json.decode(response.data) stationID = jsonTable.current_observation.station_id city = jsonTable.current_observation.observation_location.city humidity = jsonTable.current_observation.relative_humidity temperature = jsonTable.current_observation.temp_c pression = jsonTable.current_observation.pressure_mb wind = jsonTable.current_observation.wind_kph rain = jsonTable.current_observation.precip_today_metric icon = jsonTable.current_observation.icon weathericon = jsonTable.current_observation.icon_url fcstday1 = jsonTable.forecast.txt_forecast.forecastday[1].title fcst1 = jsonTable.forecast.txt_forecast.forecastday[1].fcttext_metric fcst1icon = jsonTable.forecast.txt_forecast.forecastday[1].icon_url fcstday2 = jsonTable.forecast.txt_forecast.forecastday[2].title fcst2 = jsonTable.forecast.txt_forecast.forecastday[2].fcttext_metric fcst2icon = jsonTable.forecast.txt_forecast.forecastday[2].icon_url fcst1_mobile = jsonTable.forecast.simpleforecast.forecastday[1].conditions fcst2_mobile = jsonTable.forecast.simpleforecast.forecastday[2].conditions if (stationID ~= nil) then fibaro:call(WU.selfId , "setProperty", "ui.lblStation.value", locationID); fibaro:call(WU.selfId , "setProperty", "ui.lblCity.value", city); fibaro:call(WU.selfId , "setProperty", "ui.lblTemp.value", WU.translation[WU.language]["Temperature"].." "..temperature.." °C"); fibaro:call(WU.selfId , "setProperty", "ui.lblHum.value", WU.translation[WU.language]["Humidity"].." "..humidity); fibaro:call(WU.selfId , "setProperty", "ui.lblBar.value", WU.translation[WU.language]["Pressure"].." "..pression.." mb"); fibaro:call(WU.selfId , "setProperty", "ui.lblWind.value", WU.translation[WU.language]["Wind"].." "..wind.." km/h"); fibaro:call(WU.selfId , "setProperty", "ui.lblRain.value", WU.translation[WU.language]["Rain"].." "..rain.." mm"); if (WU.now >= "03:00" and WU.now <= "15:59") then fibaro:call(WU.selfId , "setProperty", "ui.lblFcst.value",WU.translation[WU.language]["Forecast"].." "..fcstday1.." - "..fcst1_mobile); --fibaro:call(WU.selfId , "setProperty", "ui.lblIcon.value","<img src=http://jonnylarsson.se/JL/png/"..icon..".png>"); elseif (WU.now >= "16:00" and WU.now <= "23:59") then --fibaro:call(WU.selfId , "setProperty", "ui.lblIcon.value","<img src=http://jonnylarsson.se/JL/png/nt_"..icon..".png>"); fibaro:call(WU.selfId , "setProperty", "ui.lblFcst.value", WU.translation[WU.language]["Forecast"].." "..fcstday2.." - "..fcst2_mobile); end if WU.sendPush then for k,smartphoneID_and_fcstAM in ipairs(smartphoneID_and_fcstAM) do if (os.date("%H:%M") == smartphoneID_and_fcstAM[2]) then if versionCheck then versionChecker() end if WU.pushOption == "Fibaro" then fcastday = fcstday1 fcast = fcst1 fibaro:call(smartphoneID_and_fcstAM[1], "sendPush", fcstday1.." - "..fcst1) popupIMG = "http://jonnylarsson.se/JL/png/"..icon..".png" sendPopup() Debug("grey", "Sucessfully sent push message to "..smartphoneID_and_fcstAM[1]) elseif WU.pushOption == "Telegram" then Telegrambot(fcstday1.." - "..string.lower(fcst1).." - "..fcst1icon) end end end for k,smartphoneID_and_fcstPM in ipairs(smartphoneID_and_fcstPM) do if (os.date("%H:%M") == smartphoneID_and_fcstPM[2]) then if WU.pushOption == "Fibaro" then fcastday = fcstday2 fcast = fcst2 fibaro:call(smartphoneID_and_fcstPM[1] , "sendPush", fcstday2.." - "..fcst2) popupIMG = "http://jonnylarsson.se/JL/png/nt_"..icon..".png" sendPopup() Debug("grey", "Sucessfully sent push message to "smartphoneID_and_fcstPM[1]) elseif WU.pushOption == "Telegram" then Telegrambot(fcstday2.." - "..string.lower(fcst2).." - "..fcst2icon) end end end end if WU.sendPush then fibaro:call(WU.selfId , "setProperty", "ui.lblNotify.value", WU.translation[WU.language]["Push_forecast"].." = true"); else fibaro:call(WU.selfId , "setProperty", "ui.lblNotify.value",WU.translation[WU.language]["Push_forecast"].." = false"); end WU.scheduler = os.time()+updateEvery*60 fibaro:call(WU.selfId, "setProperty", "ui.lblUpdate.value", os.date("%c")); fibaro:debug(WU.translation[WU.language]["Data_processed"]) fibaro:debug(WU.translation[WU.language]["Update_interval"].." "..updateEvery) else fibaro:debug(WU.translation[WU.language]["NO_STATIONID_FOUND"]) end end sleepAndcheck = 0 while sleepAndcheck <= 20*updateEvery do fibaro:sleep(3000) sleepAndcheck = sleepAndcheck+1 if (DoNotRecheckBefore <= os.time()) and ((WU.scheduler == os.time) or (os.date("%H:%M") == smartphoneID_and_fcstAM[2]) or (os.date("%H:%M") == smartphoneID_and_fcstPM[2])) then fibaro:debug(WU.translation[WU.language]["Push_forecast"]) Debug("orange", WU.translation[WU.language]["Exiting_loop_push"]); DoNotRecheckBefore = os.time()+60 sleepAndcheck = 20*updateEvery end end end end Debug( "orange", "WU Weather - LUA Scripting by Jonny Larsson 2015/2016" ); Debug( "orange", "Version: "..version); if versionCheck then versionChecker() end createGlobalIfNotExists("WUAPI", WU.APIkey) createGlobalIfNotExists("Telegramtoken1_part1", WU.Telegramtoken1_part1) createGlobalIfNotExists("Telegramtoken1_part2", WU.Telegramtoken1_part2) createGlobalIfNotExists("Telegramchat_id1", WU.Telegramchat_id1) if WU.dualChat_ID then createGlobalIfNotExists("Telegramtoken2_part1", WU.Telegramtoken2_part1) createGlobalIfNotExists("Telegramtoken2_part2", WU.Telegramtoken2_part2) createGlobalIfNotExists("Telegramchat_id2", WU.Telegramchat_id2) end for k,smartphoneID_and_fcstAM in ipairs(smartphoneID_and_fcstAM) do Debug( "yellow", "Morning forecast push will be for ID: "..smartphoneID_and_fcstAM[1].." @ "..smartphoneID_and_fcstAM[2]); end for k,smartphoneID_and_fcstPM in ipairs(smartphoneID_and_fcstPM) do Debug( "yellow", "Afternoon forecast push will be for ID: "..smartphoneID_and_fcstPM[1].." @ "..smartphoneID_and_fcstPM[2]); end processWU() --this starts an endless loop, until an error occurs ---- END OF UPDATE ----
  14. New version again In totalt i have 12 translation in some part of the code, thanks all for your help with that. Multi language -- 2016-07-13 - Bug fixed some code for sendPush to fibaro app -- 2016-07-14 - Telegram, possible to have forecast pushed to 2 different chat_id's -- 2016-07-15 - Save all importent values to variable. -- 2016-07-15 - Added RO, GR, PT, RU and CZ translation WU.APIKey, WU.Telegramtoken1_part1, WU.Telegramtoken1_part2 and WU.Telegramchat_id1 will be stored to variables from the scene. If variable get screwed up some how, just delete them and they will be created again when you restart the scene. If you have 2 smartphones that should have forecast push with Telegram you set WU.dualChat_ID to "true" and those values will also be saved to variables. WU.language = "SW"; -- EN, FR, SW, PL, NL, DE, NO, RO, CZ, GR, PT, RU (default is en) -- WU settings WU.APIkey = "14eaxxxxxxxxxxx" -- Put your WU api key here WU.PWS = "IGVLEBOR5" -- The PWS location to get data for (Personal Weather Station) WU.LOCID = "SWXX0076" -- The location ID to get data for (City location) WU.station = "PWS" -- PWS or LOCID -- Other settings WU.smartphoneID = {281,32} -- your smartphone ID's ie 211,233,333 WU.push_fcst1 = "06:30" -- time when forecast for today will be pushed to smartphone WU.push_fcst2 = "17:00" -- time when forecast for tonight will be pushed to smartphone WU.sendPush = true -- send forecast with push WU.pushOption = "Telegram" -- Use Fibaro or Telegram? -- Telegram settings -- IMPORTANT -- -- Telegramtoken needs to splitted into 2 parts. First part1 is before the ":", part2 is after the ":" WU.Telegramtoken1_part1 = "187xxxxxx" WU.Telegramtoken1_part2 = "AAHfzhTcsKloviNxxxxxxxxxxxxxxxxx" WU.Telegramchat_id1 = "2025xxxxx" -- If you want forecast to be pushed to a second phone WU.dualChat_ID = false -- set to true if more then 1 smartphone that should have forecast pushed. WU.Telegramtoken2_part1 = "187xxxxxx" WU.Telegramtoken2_part2 = "AAHfzhTcsKloviNxxxxxxxxxxxxxxxxx" WU.Telegramchat_id2 = "2025xxxxx" Complete code --[[ %% autostart %% properties %% globals --]] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- HOWTO -- -- 1. Create a virtual device with 9 labels and set the ID to like below, else this scene will not work. -- 2. lblTemp, lblHum, lblBar, lblWind, lblRain, lblFcst, lblStation, lblUpdate, lblNotify -- 3. Change ID of virtual device in WU.selfId -- FIRST TIME USERS NEEDS TO COPY ALL CODE TO SCENE, after version 2.5.0 it should only be neccessary to update from "UPDATE FROM HERE" text -- NOTE -- -- Scheduled time you set for forecast push is just an indication of time. -- Real time will be the hour you set + minute of when scene starts. -- Script will check server version for new updated version (default = true) -- WU WeatherData - Fetch weather data from wunderground.com. Multilanguage support! -- Inspired by GEA(steven), stevenvd, Krikroff and many other users. -- Source - forum.fibaro.com, domotique-fibaro.fr and worldwideweb -- Special thanks to petergebruers from forum.fibaro.com with demo script -- -- -- PWS = Personal Weather Station -- LOCID = Public station -- -- -- 2014-03-22 - Permissions granted from Krikroff -- 2014-03-23 - Added rain and forecast, Added FR language. -- 2014-03-23 - Language variable changed to get the translation from wunderground.com in forcast -- 2014-03-24 - Added PL language -- 2014-03-24 - Select between PWS or LOCID to download weather data -- 2015-10-23 - New source code. -- 2015-10-23 - Added NL translation -- 2015-11-16 - Added DE, FR translation. Fixed some bug in the code(hardcoded smartphoneID,inch to metric for rain value) -- 2015-11-18 - Script moved to scene instead of mainloop in VD. VD is only used as GUI. -- 2015-11-18 - Send push if script cannot fetch data -- 2015-11-26 - adjustment of code. Function from sebcbien at domotique-fibaro.fr -- 2015-11-27 - Oops! Removed forecast push by mistace. -- 2016-02-11 - send push if new version of script is out -- 2016-03-31 - Added NO translation, did cleanup the code a little bit. -- 2016-03-31 - It is now posible to use Telegram as push. Change WU.pushOption value to Telegram or Fibaro. -- - also change WU.Telegramtoken and WU.Telegramchat_id to your values -- 2016-04-01 - Fixed bug when using Telegram push, forecast must send with lowercases. -- 2016-05-26 - Added support for multiple smartphone id when sending push -- 2016-05-30 - Implemented "UPDATE SECTION" -- 2016-07-13 - Bug fixed some code for sendPush to fibaro app -- 2016-07-14 - Telegram, possible to have forecast pushed to 2 different chat_id's -- 2016-07-15 - Save all importent values to variable. -- 2016-07-15 - Added RO, GR, PT, RU and CZ translation version = "{2.5.0}" WU = {} versionCheck = true -- check if new version of script exist on server WU.language = "SW"; -- EN, FR, SW, PL, NL, DE, NO, RO, CZ, GR, PT, RU (default is en) -- WU settings WU.APIkey = "14eaxxxxxxxxx" -- Put your WU api key here WU.PWS = "IGVLEBOR5" -- The PWS location to get data for (Personal Weather Station) WU.LOCID = "SWXX0076" -- The location ID to get data for (City location) WU.station = "PWS" -- PWS or LOCID -- Other settings WU.smartphoneID = {281,32} -- your smartphone ID's ie 211,233,333 WU.push_fcst1 = "06:30" -- time when forecast for today will be pushed to smartphone WU.push_fcst2 = "17:00" -- time when forecast for tonight will be pushed to smartphone WU.sendPush = true -- send forecast with push WU.pushOption = "Telegram" -- Use Fibaro or Telegram? -- Telegram settings -- IMPORTANT -- -- Telegramtoken needs to splitted into 2 parts. First part1 is before the ":", part2 is after the ":" WU.Telegramtoken1_part1 = "1877xxxxx" WU.Telegramtoken1_part2 = "AAHfzhTcsxxxxxxxxxxxxxxxxxx" WU.Telegramchat_id1 = "2025xxxxx" -- If you want forecast to be pushed to a second phone WU.dualChat_ID = false -- set to true if more then 1 smartphone that should have forecast pushed. WU.Telegramtoken2_part1 = "1877xxxxx" WU.Telegramtoken2_part2 = "AAHfzhTcsxxxxxxxxxxxxxxxxxx" WU.Telegramchat_id2 = "2025xxxxx" updateEvery = 5 -- get data every xx minutes WU.selfId = 150 -- ID of virtual device ---- UPDATE FROM HERE ---- -- Read settings from variable if not(fibaro:getGlobal("WUAPI") == nil) and (fibaro:getGlobal("Telegramtoken_part1") == nil) and (fibaro:getGlobal("Telegramtoken_part2") == nil) and (fibaro:getGlobal("Telegramchat_id") == nil) and (fibaro:getGlobal("Telegramchat_id2") == nil ) then WU.APIkey = fibaro:getGlobal("WUAPI") WU.Telegramtoken1 = fibaro:getGlobal("Telegramtoken1_part1")..":"..fibaro:getGlobal("Telegramtoken1_part2") WU.Telegramchat_id1 = fibaro:getGlobal("Telegramchat_id1") WU.Telegramurl1 = "https://api.telegram.org/bot"..WU.Telegramtoken1.."/sendMessage?chat_id="..WU.Telegramchat_id1.."&text=" if WU.dualChat_ID then WU.Telegramtoken2 = fibaro:getGlobal("Telegramtoken2_part1")..":" fibaro:getGlobal("Telegramtoken2_part2") WU.Telegramchat_id2 = fibaro:getGlobal("Telegramchat_id2") WU.Telegramurl2 = "https://api.telegram.org/bot"..WU.Telegramtoken2.."/sendMessage?chat_id="..WU.Telegramchat_id2.."&text=" end end -- End read settings from variable WU.translation = {true} WU.currentDate = os.date("*t"); DoNotRecheckBefore = os.time() WU.scheduler = os.time()+60*updateEvery WU.translation["EN"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push forecast", Temperature = "Temperature", Humidity = "Humidity", Pressure = "Pressure", Wind = "Wind", Rain = "Rain", Forecast = "Forecast", Station = "Station", Fetched = "Fetched", Data_processed = "Data processed", Update_interval = "Next update will be in (min)", No_data_fetched = "No data fetched", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", NO_STATIONID_FOUND = "No stationID found", NO_DATA_FOUND = "No data found" } WU.translation["FR"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push prévisions", Temperature = "Température", Humidity = "Humidité", Pressure = "Pression", Wind = "Vent", Rain = "Pluie", Forecast = "Prévisions", Station = "Station", Fetched = "Reçu", Data_processed = "Données Analysées", Update_interval = "Prochaine update prévue dans (min)", No_data_fetched = "Pas de données reçues", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", NO_STATIONID_FOUND = "StationID non trouvée", NO_DATA_FOUND = "Pas de données disponibles" } WU.translation["SW"] = { Exiting_loop_push = "Push loop avslutad", Push_forecast = "Push forecast", Temperature = "Temperatur", Humidity = "Fuktighet", Pressure = "Barometer", Wind = "Vind", Rain = "Regn", Forecast = "Prognos", Station = "Station", Fetched = "Hämtat", Data_processed = "All data processat", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", Update_interval = "Nästa uppdatering är om (min)", No_data_fetched = "Inget data hämtat", NO_STATIONID_FOUND = "StationID ej funnet", NO_DATA_FOUND = "Ingen data hos WU" } WU.translation["PL"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push prognoza", Temperature = "Temperatura", Humidity = "Wilgotność", Pressure = "Pressure", Wind = "Wiatr", Rain = "Deszcz", Forecast = "Prognoza", Station = "Stacja", Fetched = "Nie pobrano danyc", Data_processed = "Dane przetworzone", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", No_data_fetched = "Brak danych", Update_interval = "Następna aktualizacja za (min)", NO_STATIONID_FOUND = "No stationID found", NO_DATA_FOUND = "Brak danych" } WU.translation["NL"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push verwachting", Temperature = "Temperatuur", Humidity = "Vochtigheid", Pressure = "Druk", Wind = "Wind", Rain = "Regen", Forecast = "Verwachting", Station = "Weerstation", Fetched = "Ontvangen", Data_processed = "Gegevens verwerkt", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", Update_interval = "Volgende update in (min)", No_data_fetched = "Geen gegevens ontvangen", NO_STATIONID_FOUND = "Geen stationID gevonden", NO_DATA_FOUND = "Geen gegevens gevonden" } WU.translation["DE"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push vorhersage", Temperature = "Temperatur", Humidity = "Luftfeuchtigkeit", Pressure = "Luftdruck", Wind = "Wind", Rain = "Regen", Forecast = "Vorhersage", Station = "Station", Fetched = "Abgerufen", Data_processed = "Daten verarbeitet", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", No_data_fetched = "Keine Daten abgerufen", Update_interval = "Das nächste Update in (min)", NO_STATIONID_FOUND = "Keine stationID gefunden", NO_DATA_FOUND = "Keine Daten gefunden" } WU.translation["NO"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push værmelding", Temperature = "Temperatur", Humidity = "Fuktighet", Pressure = "Barometer", Wind = "Vind", Rain = "Regn", Forecast = "Prognose", Station = "Stasjon", Fetched = "Hentet", Data_processed = "All data prosessert", Update_interval = "Neste oppdatering om (min)", No_data_fetched = "Ingen data hentet", NO_STATIONID_FOUND = "StasjonID ikke funnet", NO_DATA_FOUND = "Ingen data hos WU" } WU.translation["CZ"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push forecast", Temperature = "Teplota", Humidity = "Vlhkost", Pressure = "(Atmosférický) Tlak", Wind = "Vítr", Rain = "Déšť ", Forecast = "Předpověď", Station = "Stanice", Fetched = "Předána", Data_processed = "Data_zpracována", Update_interval = "Časová_prodleva_mezi_aktualizacemi", No_data_fetched = "Data_nebyla_předána", NO_STATIONID_FOUND = "Stanice_nenalezena", NO_DATA_FOUND = "Data_Nenalezena" } WU.translation["RO"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Prognoza apăsare", Temperature = "Temperatura", Humidity = "Umiditate", Pressure = "Presiune", Wind = "Vant", Rain = "Ploaie", Forecast = "Prognoza", Station = "Statie", Fetched = "Preluat", Data_processed = "Datele prelucrate", Update_interval = "Urmatorul update va fi in (min)", No_data_fetched = "Nu exista date preluate", NO_STATIONID_FOUND = "Nu a fost gasit stationID ", NO_DATA_FOUND = "Datele nu au fost gasite" } WU.translation["GR"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Πρόγνωση push", Temperature = "Θερμοκρασία", Humidity = "Υγρασία", Pressure = "Πίεση", Wind = "Άνεμος", Rain = "Βροχή", Forecast = "Πρόβλεψη", Station = "Σταθμός", Fetched = "Παραλήφθηκαν", Data_processed = "Επεξεργασμένα δεδομένα", Update_interval = "Η επόμενη ενημέρωση θα γίνει σε (min)", No_data_fetched = "Δεν παραλήφθηκαν δεδομένα", NO_STATIONID_FOUND = "Δεν βρέθηκε το Station ID", NO_DATA_FOUND = "Δεν βρέθηκαν δεδομένα" } WU.translation["PT"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Previsão do impulso", Temperature = "Temperatura", Humidity = "Humidade", Pressure = "Pressão", Wind = "Vento", Rain = "Chuva", Forecast = "Previsão", Station = "Estação", Fetched = "Procurar", Data_processed = "Dados processados", Update_interval = "Próxima atualização será em (min)", No_data_fetched = "Não foram encontrados dados", NO_STATIONID_FOUND = "Não foi detetada nenhuma estação", NO_DATA_FOUND = "Não foram encontrados dados" } WU.translation["RU"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Прогноз Нажмите", Temperature = "Температура", Humidity = "Влажность", Pressure = "Давление", Wind = "Ветер", Rain = "Дождь", Forecast = "Прогноз", Station = "Станция", Fetched = "Получено", Data_processed = "Данные обработаны", Update_interval = "Следующее обновление через (мин.)", No_data_fetched = "Данные не получены", NO_STATIONID_FOUND = "Данная станция не найдена", NO_DATA_FOUND = "Данные не найдены" } if WU.station == "LOCID" then locationID = WU.LOCID elseif WU.station == "PWS" then locationID = WU.PWS end Debug = function ( color, message ) fibaro:debug(string.format('<%s style="color:%s;">%s</%s>', "span", color, message, "span")); end local function log(str) if debug then fibaro:debug(str); end; end local function errorlog(str) fibaro:debug("<font color='red'>"..str.."</font>"); end function Telegrambot(msg) local selfhttp = net.HTTPClient({timeout=2000}) url = WU.Telegramurl1 .. msg selfhttp:request(url, { options={ headers = selfhttp.controlHeaders, data = requestBody, method = 'GET' }, success = function(status) local result = json.decode(status.data); if result.ok == true then Debug("grey", "Sucessfully sent message to Telegram Bot...") else --errorlog("failed"); print(status.data); end end, error = function(error) --errorlog("ERROR") Debug("red", error) end }) if WU.dualChat_ID then url2 = WU.Telegramurl2 .. msg selfhttp:request(url2, { options={ headers = selfhttp.controlHeaders, data = requestBody, method = 'GET' }, success = function(status) local result = json.decode(status.data); if result.ok == true then Debug("grey", "Sucessfully sent message to Telegram Bot...") else --errorlog("failed"); print(status.data); end end, error = function(error) --errorlog("ERROR") Debug("red", error) end }) end end function versionChecker() local function getMethod(requestUrl, successCallback, errorCallback) local http = net.HTTPClient() http:request(requestUrl, { options = { method = 'GET', headers = { }, }, success = successCallback, error = errorCallback }) end content = "WUWeather.lua" local url = 'http://jonnylarsson.se/JL/'..content getMethod(url, function(resp) s = resp.data serverVersion = string.match(s, "{(.-)}"); scriptVersion = string.match(version, "{(.-)}"); if serverVersion > scriptVersion then Debug("grey", "Checking script version...") Debug("yellow", "There is a new version out! "..'<a href="http://jonnylarsson.se/JL/WUWeather.lua" target="_blank" style="display:inline;color:Cyan">Get it!</a>') if WU.sendPush then if WU.pushOption == "Fibaro" then fibaro:call(WU.smartphoneID , "sendPush", WU.translation[WU.language]["new_version"].." "..WU.translation[WU.language]["script_url"]) elseif WU.pushOption == "Telegram" then Telegrambot(WU.translation[WU.language]["new_version"].." "..WU.translation[WU.language]["script_url"]) end end end end, function(err) print('error' .. err) end ) end local http = net.HTTPClient() local function errorWU(err) if WU.pushOption == "Fibaro" then fibaro:call(WU.smartphoneID , "sendPush", "[WUWeather scene]. Error: "..err ) elseif WU.pushOption == "Telegram" then Telegrambot("[WUWeather scene]. Error: "..err ) end Debug( "red", "[HTTPClient:request]. Error: "..err ); end local function sendPopup() -- variable containing path of Motion Sensor’s icon local imgUrl = popupIMG -- pop-up call HomeCenter.PopupService.publish({ -- title (required) title = 'Weather forecast', -- subtitle(optional), e.g. time and date of the pop-up call subtitle = os.date("%I:%M:%S %p | %B %d, %Y"), -- content header (optional) contentTitle = 'Forecast from WU Weather', -- content (required) contentBody = fcastday.." - "..fcast, -- notification image (assigned from the variable) img = imgUrl, -- type of the pop-up type = 'Info', }) end function createGlobalIfNotExists(varName, defaultValue) if (fibaro:getGlobal(varName) == nil) then Debug("cyan", "Creating the variable: "..varName.." with value: "..defaultValue) newVar = {} newVar.name = varName newVar.value = defaultValue local http = net.HTTPClient() http:request("http://127.0.0.1:11111/api/globalVariables", { options = { method = 'POST', data = json.encode(newVar)}}) end end local function processWU(response) http:request("http://api.wunderground.com/api/"..WU.APIkey.."/conditions/forecast/lang:"..WU.language.."/q/"..WU.station..":"..locationID..".json",{ options = {method = 'GET'}, success = processWU, error = errorWU }) Debug( "green", "Now downloading data from www.wunderground.com"); if response then -- the first time you enter the loop, this will be nil if response.status~=200 then Debug( "red", "Server returned an error, but will retry. Error: "..response.status) else WU.now = os.date("%H:%M") jsonTable = json.decode(response.data) stationID = jsonTable.current_observation.station_id city = jsonTable.current_observation.observation_location.city humidity = jsonTable.current_observation.relative_humidity temperature = jsonTable.current_observation.temp_c pression = jsonTable.current_observation.pressure_mb wind = jsonTable.current_observation.wind_kph rain = jsonTable.current_observation.precip_today_metric icon = jsonTable.current_observation.icon weathericon = jsonTable.current_observation.icon_url fcstday1 = jsonTable.forecast.txt_forecast.forecastday[1].title fcst1 = jsonTable.forecast.txt_forecast.forecastday[1].fcttext_metric fcst1icon = jsonTable.forecast.txt_forecast.forecastday[1].icon_url fcstday2 = jsonTable.forecast.txt_forecast.forecastday[2].title fcst2 = jsonTable.forecast.txt_forecast.forecastday[2].fcttext_metric fcst2icon = jsonTable.forecast.txt_forecast.forecastday[2].icon_url if (stationID ~= nil) then fibaro:call(WU.selfId , "setProperty", "ui.lblStation.value", locationID); fibaro:call(WU.selfId , "setProperty", "ui.lblCity.value", city); fibaro:call(WU.selfId , "setProperty", "ui.lblTemp.value", WU.translation[WU.language]["Temperature"].." "..temperature.." °C"); fibaro:call(WU.selfId , "setProperty", "ui.lblHum.value", WU.translation[WU.language]["Humidity"].." "..humidity); fibaro:call(WU.selfId , "setProperty", "ui.lblBar.value", WU.translation[WU.language]["Pressure"].." "..pression.." mb"); fibaro:call(WU.selfId , "setProperty", "ui.lblWind.value", WU.translation[WU.language]["Wind"].." "..wind.." km/h"); fibaro:call(WU.selfId , "setProperty", "ui.lblRain.value", WU.translation[WU.language]["Rain"].." "..rain.." mm"); if (WU.now >= "03:00" and WU.now <= "15:59") then fibaro:call(WU.selfId , "setProperty", "ui.lblFcst.value",WU.translation[WU.language]["Forecast"].." "..fcstday1.." - "..fcst1); --fibaro:call(WU.selfId , "setProperty", "ui.lblIcon.value","<img src=http://jonnylarsson.se/JL/png/"..icon..".png>"); elseif (WU.now >= "16:00" and WU.now <= "23:59") then --fibaro:call(WU.selfId , "setProperty", "ui.lblIcon.value","<img src=http://jonnylarsson.se/JL/png/nt_"..icon..".png>"); fibaro:call(WU.selfId , "setProperty", "ui.lblFcst.value", WU.translation[WU.language]["Forecast"].." "..fcstday2.." - "..fcst2); end if WU.sendPush then if (os.date("%H:%M") == WU.push_fcst1) then if versionCheck then versionChecker() end if WU.pushOption == "Fibaro" then fcastday = fcstday1 fcast = fcst1 for i, j in pairs(WU.smartphoneID) do fibaro:call(j, "sendPush", fcstday1.." - "..fcst1) popupIMG = "http://jonnylarsson.se/JL/png/"..icon..".png" sendPopup() end elseif WU.pushOption == "Telegram" then Telegrambot(fcstday1.." - "..string.lower(fcst1).." - "..fcst1icon) end elseif (os.date("%H:%M") == WU.push_fcst2) then if WU.pushOption == "Fibaro" then fcastday = fcstday2 fcast = fcst2 for i, j in pairs(WU.smartphoneID) do fibaro:call(j , "sendPush", fcstday2.." - "..fcst2) popupIMG = "http://jonnylarsson.se/JL/png/nt_"..icon..".png" sendPopup() end elseif WU.pushOption == "Telegram" then Telegrambot(fcstday2.." - "..string.lower(fcst2).." - "..fcst2icon) end end end if WU.sendPush then fibaro:call(WU.selfId , "setProperty", "ui.lblNotify.value", WU.translation[WU.language]["Push_forecast"].." = true"); else fibaro:call(WU.selfId , "setProperty", "ui.lblNotify.value",WU.translation[WU.language]["Push_forecast"].." = false"); end WU.scheduler = os.time()+updateEvery*60 fibaro:call(WU.selfId, "setProperty", "ui.lblUpdate.value", os.date("%c")); fibaro:debug(WU.translation[WU.language]["Data_processed"]) fibaro:debug(WU.translation[WU.language]["Update_interval"].." "..updateEvery) else fibaro:debug(WU.translation[WU.language]["NO_STATIONID_FOUND"]) end end sleepAndcheck = 0 while sleepAndcheck <= 20*updateEvery do fibaro:sleep(3000) sleepAndcheck = sleepAndcheck+1 if (DoNotRecheckBefore <= os.time()) and ((WU.scheduler == os.time) or (os.date("%H:%M") == WU.push_fcst1) or (os.date("%H:%M") == WU.push_fcst2)) then fibaro:debug(WU.translation[WU.language]["Push_forecast"]) Debug("orange", WU.translation[WU.language]["Exiting_loop_push"]); DoNotRecheckBefore = os.time()+60 sleepAndcheck = 20*updateEvery end end end end Debug( "orange", "WU Weather - LUA Scripting by Jonny Larsson 2015/2016" ); Debug( "orange", "Version: "..version); if versionCheck then versionChecker() end createGlobalIfNotExists("WUAPI", WU.APIkey) createGlobalIfNotExists("Telegramtoken1_part1", WU.Telegramtoken1_part1) createGlobalIfNotExists("Telegramtoken1_part2", WU.Telegramtoken1_part2) createGlobalIfNotExists("Telegramchat_id1", WU.Telegramchat_id1) if WU.dualChat_ID then createGlobalIfNotExists("Telegramtoken2_part1", WU.Telegramtoken2_part1) createGlobalIfNotExists("Telegramtoken2_part2", WU.Telegramtoken2_part2) createGlobalIfNotExists("Telegramchat_id2", WU.Telegramchat_id2) end Debug( "yellow", "Morning forecast push will be: "..WU.push_fcst1); Debug( "yellow", "Afternoon forecast push will be: "..WU.push_fcst2); processWU() --this starts an endless loop, until an error occurs ---- END OF UPDATE ----
  15. * New* This version can handle 2 different chat_id's for Telegram, means you can send to 2 different phones if you like. Using Fibaro app as receiver of forecast - corrected a bug in the code when there is more then 1 id of phones IMPORTENT You need to paste all new LUA code to your scene, not just from "Update from here" Remember to write down you API key for Weather Wunderground, token for Telegram and chat_id --[[ %% autostart %% properties %% globals --]] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- HOWTO -- -- 1. Create a virtual device with 9 labels and set the ID to like below, else this scene will not work. -- 2. lblTemp, lblHum, lblBar, lblWind, lblRain, lblFcst, lblStation, lblUpdate, lblNotify -- 3. Change ID of virtual device in WU.selfId -- NOTE -- -- Scheduled time you set for forecast push is just an indication of time. -- Real time will be the hour you set + minute of when scene starts. -- Script will check server version for new updated version (default = true) -- WU WeatherData - Fetch weather data from wunderground.com. Multilanguage support! -- Inspired by GEA(steven), stevenvd, Krikroff and many other users. -- Source - forum.fibaro.com, domotique-fibaro.fr and worldwideweb -- Special thanks to petergebruers from forum.fibaro.com with demo script -- -- -- PWS = Personal Weather Station -- LOCID = Public station -- -- -- 2014-03-22 - Permissions granted from Krikroff -- 2014-03-23 - Added rain and forecast, Added FR language. -- 2014-03-23 - Language variable changed to get the translation from wunderground.com in forcast -- 2014-03-24 - Added PL language -- 2014-03-24 - Select between PWS or LOCID to download weather data -- 2015-10-23 - New source code. -- 2015-10-23 - Added NL translation -- 2015-11-16 - Added DE, FR translation. Fixed some bug in the code(hardcoded smartphoneID,inch to metric for rain value) -- 2015-11-18 - Script moved to scene instead of mainloop in VD. VD is only used as GUI. -- 2015-11-18 - Send push if script cannot fetch data -- 2015-11-26 - adjustment of code. Function from sebcbien at domotique-fibaro.fr -- 2015-11-27 - Oops! Removed forecast push by mistace. -- 2016-02-11 - send push if new version of script is out -- 2016-03-31 - Added NO translation, did cleanup the code a little bit. -- 2016-03-31 - It is now posible to use Telegram as push. Change WU.pushOption value to Telegram or Fibaro. -- - also change WU.Telegramtoken and WU.Telegramchat_id to your values -- 2016-04-01 - Fixed bug when using Telegram push, forecast must send with lowercases. -- 2016-05-26 - Added support for multiple smartphone id when sending push -- 2016-05-30 - Implemented "UPDATE SECTION" -- 2016-07-13 - Bug fixed some code for sendPush to fibaro app -- 2016-07-14 - Telegram, possible to have forecast pushed to 2 different chat_id's version = "{2.4.0}" WU = {} versionCheck = true -- check if new version of script exist on server WU.language = "SW"; -- EN, FR, SW, PL, NL, DE, NO (default is en) -- WU settings WU.APIkey = "xxxxxxxxx" -- Put your WU api key here WU.PWS = "IGVLEBOR5" -- The PWS location to get data for (Personal Weather Station) WU.LOCID = "SWXX0076" -- The location ID to get data for (City location) WU.station = "PWS" -- PWS or LOCID -- Other settings WU.smartphoneID = {279,32} -- your smartphone ID's ie 211,233,333 WU.push_fcst1 = "06:30" -- time when forecast for today will be pushed to smartphone WU.push_fcst2 = "17:00" -- time when forecast for tonight will be pushed to smartphone WU.sendPush = true -- send forecast with push WU.pushOption = "Telegram" -- Use Fibaro or Telegram? -- Telegram settings WU.dualChat_ID = false -- set to true if more then 1 smartphone that should have forecast pushed. WU.Telegramtoken = "YOUR:TOKEN" WU.Telegramchat_id = "2025xxxxx" WU.Telegramchat_id2 = "2025xxxxx" WU.Telegramurl = "https://api.telegram.org/bot"..WU.Telegramtoken.."/sendMessage?chat_id="..WU.Telegramchat_id.."&text=" WU.Telegramurl2 = "https://api.telegram.org/bot"..WU.Telegramtoken.."/sendMessage?chat_id="..WU.Telegramchat_id2.."&text=" updateEvery = 1 -- get data every xx minutes WU.selfId = 150 -- ID of virtual device ---- UPDATE FROM HERE ---- WU.translation = {true} WU.currentDate = os.date("*t"); DoNotRecheckBefore = os.time() WU.scheduler = os.time()+60*updateEvery WU.translation["EN"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push forecast", Temperature = "Temperature", Humidity = "Humidity", Pressure = "Pressure", Wind = "Wind", Rain = "Rain", Forecast = "Forecast", Station = "Station", Fetched = "Fetched", Data_processed = "Data processed", Update_interval = "Next update will be in (min)", No_data_fetched = "No data fetched", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", NO_STATIONID_FOUND = "No stationID found", NO_DATA_FOUND = "No data found" } WU.translation["FR"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push prévisions", Temperature = "Température", Humidity = "Humidité", Pressure = "Pression", Wind = "Vent", Rain = "Pluie", Forecast = "Prévisions", Station = "Station", Fetched = "Reçu", Data_processed = "Données Analysées", Update_interval = "Prochaine update prévue dans (min)", No_data_fetched = "Pas de données reçues", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", NO_STATIONID_FOUND = "StationID non trouvée", NO_DATA_FOUND = "Pas de données disponibles" } WU.translation["SW"] = { Exiting_loop_push = "Push loop avslutad", Push_forecast = "Push forecast", Temperature = "Temperatur", Humidity = "Fuktighet", Pressure = "Barometer", Wind = "Vind", Rain = "Regn", Forecast = "Prognos", Station = "Station", Fetched = "Hämtat", Data_processed = "All data processat", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", Update_interval = "Nästa uppdatering är om (min)", No_data_fetched = "Inget data hämtat", NO_STATIONID_FOUND = "StationID ej funnet", NO_DATA_FOUND = "Ingen data hos WU" } WU.translation["PL"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push prognoza", Temperature = "Temperatura", Humidity = "Wilgotność", Pressure = "Pressure", Wind = "Wiatr", Rain = "Deszcz", Forecast = "Prognoza", Station = "Stacja", Fetched = "Nie pobrano danyc", Data_processed = "Dane przetworzone", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", No_data_fetched = "Brak danych", Update_interval = "Następna aktualizacja za (min)", NO_STATIONID_FOUND = "No stationID found", NO_DATA_FOUND = "Brak danych" } WU.translation["NL"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push verwachting", Temperature = "Temperatuur", Humidity = "Vochtigheid", Pressure = "Druk", Wind = "Wind", Rain = "Regen", Forecast = "Verwachting", Station = "Weerstation", Fetched = "Ontvangen", Data_processed = "Gegevens verwerkt", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", Update_interval = "Volgende update in (min)", No_data_fetched = "Geen gegevens ontvangen", NO_STATIONID_FOUND = "Geen stationID gevonden", NO_DATA_FOUND = "Geen gegevens gevonden" } WU.translation["DE"] = { Exiting_loop_push = "Exiting_loop_push", Push_forecast = "Push vorhersage", Temperature = "Temperatur", Humidity = "Luftfeuchtigkeit", Pressure = "Luftdruck", Wind = "Wind", Rain = "Regen", Forecast = "Vorhersage", Station = "Station", Fetched = "Abgerufen", Data_processed = "Daten verarbeitet", new_version = "New version of WUWeather.lua script is out! ", script_url = "http://jonnylarsson.se/JL/", No_data_fetched = "Keine Daten abgerufen", Update_interval = "Das nächste Update in (min)", NO_STATIONID_FOUND = "Keine stationID gefunden", NO_DATA_FOUND = "Keine Daten gefunden" } WU.translation["NO"] = { Push_forecast = "Push værmelding", Temperature = "Temperatur", Humidity = "Fuktighet", Pressure = "Barometer", Wind = "Vind", Rain = "Regn", Forecast = "Prognose", Station = "Stasjon", Fetched = "Hentet", Data_processed = "All data prosessert", Update_interval = "Neste oppdatering om (min)", No_data_fetched = "Ingen data hentet", NO_STATIONID_FOUND = "StasjonID ikke funnet", NO_DATA_FOUND = "Ingen data hos WU" } if WU.station == "LOCID" then locationID = WU.LOCID elseif WU.station == "PWS" then locationID = WU.PWS end Debug = function ( color, message ) fibaro:debug(string.format('<%s style="color:%s;">%s</%s>', "span", color, message, "span")); end local function log(str) if debug then fibaro:debug(str); end; end local function errorlog(str) fibaro:debug("<font color='red'>"..str.."</font>"); end function Telegrambot(msg) local selfhttp = net.HTTPClient({timeout=2000}) url = WU.Telegramurl .. msg selfhttp:request(url, { options={ headers = selfhttp.controlHeaders, data = requestBody, method = 'GET' }, success = function(status) local result = json.decode(status.data); if result.ok == true then Debug("grey", "Sucessfully sent message to Telegram Bot...") else --errorlog("failed"); print(status.data); end end, error = function(error) --errorlog("ERROR") Debug("red", error) end }) if WU.dualChat_ID then url2 = WU.Telegramurl2 .. msg selfhttp:request(url2, { options={ headers = selfhttp.controlHeaders, data = requestBody, method = 'GET' }, success = function(status) local result = json.decode(status.data); if result.ok == true then Debug("grey", "Sucessfully sent message to Telegram Bot...") else --errorlog("failed"); print(status.data); end end, error = function(error) --errorlog("ERROR") Debug("red", error) end }) end end function versionChecker() local function getMethod(requestUrl, successCallback, errorCallback) local http = net.HTTPClient() http:request(requestUrl, { options = { method = 'GET', headers = { }, }, success = successCallback, error = errorCallback }) end content = "WUWeather.lua" local url = 'http://jonnylarsson.se/JL/'..content getMethod(url, function(resp) s = resp.data serverVersion = string.match(s, "{(.-)}"); scriptVersion = string.match(version, "{(.-)}"); if serverVersion > scriptVersion then Debug("grey", "Checking script version...") Debug("yellow", "There is a new version out! "..'<a href="http://jonnylarsson.se/JL/WUWeather.lua" target="_blank" style="display:inline;color:Cyan">Get it!</a>') if WU.sendPush then if WU.pushOption == "Fibaro" then fibaro:call(WU.smartphoneID , "sendPush", WU.translation[WU.language]["new_version"].." "..WU.translation[WU.language]["script_url"]) elseif WU.pushOption == "Telegram" then Telegrambot(WU.translation[WU.language]["new_version"].." "..WU.translation[WU.language]["script_url"]) end end end end, function(err) print('error' .. err) end ) end local http = net.HTTPClient() local function errorWU(err) if WU.pushOption == "Fibaro" then fibaro:call(WU.smartphoneID , "sendPush", "[WUWeather scene]. Error: "..err ) elseif WU.pushOption == "Telegram" then Telegrambot("[WUWeather scene]. Error: "..err ) end Debug( "red", "[HTTPClient:request]. Error: "..err ); end local function sendPopup() -- variable containing path of Motion Sensor’s icon local imgUrl = popupIMG -- pop-up call HomeCenter.PopupService.publish({ -- title (required) title = 'Weather forecast', -- subtitle(optional), e.g. time and date of the pop-up call subtitle = os.date("%I:%M:%S %p | %B %d, %Y"), -- content header (optional) contentTitle = 'Forecast from WU Weather', -- content (required) contentBody = fcastday.." - "..fcast, -- notification image (assigned from the variable) img = imgUrl, -- type of the pop-up type = 'Info', }) end local function processWU(response) http:request("http://api.wunderground.com/api/"..WU.APIkey.."/conditions/forecast/lang:"..WU.language.."/q/"..WU.station..":"..locationID..".json",{ options = {method = 'GET'}, success = processWU, error = errorWU }) Debug( "green", "Now downloading data from www.wunderground.com"); if response then -- the first time you enter the loop, this will be nil if response.status~=200 then Debug( "red", "Server returned an error, but will retry. Error: "..response.status) else WU.now = os.date("%H:%M") jsonTable = json.decode(response.data) stationID = jsonTable.current_observation.station_id city = jsonTable.current_observation.observation_location.city humidity = jsonTable.current_observation.relative_humidity temperature = jsonTable.current_observation.temp_c pression = jsonTable.current_observation.pressure_mb wind = jsonTable.current_observation.wind_kph rain = jsonTable.current_observation.precip_today_metric icon = jsonTable.current_observation.icon weathericon = jsonTable.current_observation.icon_url fcstday1 = jsonTable.forecast.txt_forecast.forecastday[1].title fcst1 = jsonTable.forecast.txt_forecast.forecastday[1].fcttext_metric fcst1icon = jsonTable.forecast.txt_forecast.forecastday[1].icon_url fcstday2 = jsonTable.forecast.txt_forecast.forecastday[2].title fcst2 = jsonTable.forecast.txt_forecast.forecastday[2].fcttext_metric fcst2icon = jsonTable.forecast.txt_forecast.forecastday[2].icon_url if (stationID ~= nil) then fibaro:call(WU.selfId , "setProperty", "ui.lblStation.value", locationID); fibaro:call(WU.selfId , "setProperty", "ui.lblCity.value", city); fibaro:call(WU.selfId , "setProperty", "ui.lblTemp.value", WU.translation[WU.language]["Temperature"].." "..temperature.." °C"); fibaro:call(WU.selfId , "setProperty", "ui.lblHum.value", WU.translation[WU.language]["Humidity"].." "..humidity); fibaro:call(WU.selfId , "setProperty", "ui.lblBar.value", WU.translation[WU.language]["Pressure"].." "..pression.." mb"); fibaro:call(WU.selfId , "setProperty", "ui.lblWind.value", WU.translation[WU.language]["Wind"].." "..wind.." km/h"); fibaro:call(WU.selfId , "setProperty", "ui.lblRain.value", WU.translation[WU.language]["Rain"].." "..rain.." mm"); if (WU.now >= "03:00" and WU.now <= "15:59") then fibaro:call(WU.selfId , "setProperty", "ui.lblFcst.value",WU.translation[WU.language]["Forecast"].." "..fcstday1.." - "..fcst1); --fibaro:call(WU.selfId , "setProperty", "ui.lblIcon.value","<img src=http://jonnylarsson.se/JL/png/"..icon..".png>"); elseif (WU.now >= "16:00" and WU.now <= "23:59") then --fibaro:call(WU.selfId , "setProperty", "ui.lblIcon.value","<img src=http://jonnylarsson.se/JL/png/nt_"..icon..".png>"); fibaro:call(WU.selfId , "setProperty", "ui.lblFcst.value", WU.translation[WU.language]["Forecast"].." "..fcstday2.." - "..fcst2); end if WU.sendPush then if (os.date("%H:%M") == WU.push_fcst1) then if versionCheck then versionChecker() end if WU.pushOption == "Fibaro" then fcastday = fcstday1 fcast = fcst1 for i, j in pairs(WU.smartphoneID) do fibaro:call(j, "sendPush", fcstday1.." - "..fcst1) popupIMG = "http://jonnylarsson.se/JL/png/"..icon..".png" sendPopup() end elseif WU.pushOption == "Telegram" then Telegrambot(fcstday1.." - "..string.lower(fcst1).." - "..fcst1icon) end elseif (os.date("%H:%M") == WU.push_fcst2) then if WU.pushOption == "Fibaro" then fcastday = fcstday2 fcast = fcst2 for i, j in pairs(WU.smartphoneID) do fibaro:call(j , "sendPush", fcstday2.." - "..fcst2) popupIMG = "http://jonnylarsson.se/JL/png/nt_"..icon..".png" sendPopup() end elseif WU.pushOption == "Telegram" then Telegrambot(fcstday2.." - "..string.lower(fcst2).." - "..fcst2icon) end end end if WU.sendPush then fibaro:call(WU.selfId , "setProperty", "ui.lblNotify.value", WU.translation[WU.language]["Push_forecast"].." = true"); else fibaro:call(WU.selfId , "setProperty", "ui.lblNotify.value",WU.translation[WU.language]["Push_forecast"].." = false"); end WU.scheduler = os.time()+updateEvery*60 fibaro:call(WU.selfId, "setProperty", "ui.lblUpdate.value", os.date("%c")); fibaro:debug(WU.translation[WU.language]["Data_processed"]) fibaro:debug(WU.translation[WU.language]["Update_interval"].." "..updateEvery) else fibaro:debug(WU.translation[WU.language]["NO_STATIONID_FOUND"]) end end sleepAndcheck = 0 while sleepAndcheck <= 20*updateEvery do fibaro:sleep(3000) sleepAndcheck = sleepAndcheck+1 if (DoNotRecheckBefore <= os.time()) and ((WU.scheduler == os.time) or (os.date("%H:%M") == WU.push_fcst1) or (os.date("%H:%M") == WU.push_fcst2)) then fibaro:debug(WU.translation[WU.language]["Push_forecast"]) Debug("orange", WU.translation[WU.language]["Exiting_loop_push"]); DoNotRecheckBefore = os.time()+60 sleepAndcheck = 20*updateEvery end end end end Debug( "orange", "WU Weather - LUA Scripting by Jonny Larsson 2015/2016" ); Debug( "orange", "Version: "..version); if versionCheck then versionChecker() end Debug( "yellow", "Morning forecast push will be: "..WU.push_fcst1); Debug( "yellow", "Afternoon forecast push will be: "..WU.push_fcst2); processWU() --this starts an endless loop, until an error occurs ---- END OF UPDATE ----
  16. Hi. I'm looking for a sample on how to increase light of a dimmer when button on keypad (remote) is pressed. Right now I have a fibaro dimmer module and a keypad. Currently I've implemented the scene below to test. The lights are now turned on/off. The keypad sends 12 when button is held down, and 11 when it is released. What I would like to accomplish is to increase the current light value while the button is held down, and off course do the opposite with another button. Any tips is appreciated. Cheers ! --[[ %% properties 100 sceneActivation %% globals --]] -- NodON Configuration -- -- Left Up = 10 -- Left UP press = 12 -- Left UP release = 11 -- Left Down = 30 -- Right Up = 20 -- Right Down = 40 local DeviceID1 = 118 -- Light Spisestue local DeviceID2 = 114 -- Light TV-Stue local ButtonPressed = fibaro:getValue(100, "sceneActivation"); if ( tonumber(ButtonPressed) == 10) then fibaro:call(DeviceID1, "turnOn"); elseif ( tonumber(ButtonPressed) == 30) then fibaro:call(DeviceID1, "turnOff"); elseif ( tonumber(ButtonPressed) == 20) then fibaro:call(DeviceID2, "turnOn"); elseif ( tonumber(ButtonPressed) == 40) then fibaro:call(DeviceID2, "turnOff"); else fibaro:debug(ButtonPressed); end
  17. Have fun! -- NOTICE TO CHANGE DEVICES ID's: --[[ %% properties 7 value 17 value %% globals --]] -- BATHROOM SCENE FUNCTIONALITY: -- No extra Global variables needed! -- Automatic light depending of opening and closing door -- Time to enter - detecting another situations, like cleaning bathroom -- NOTICE TO CHANGE DEVICES ID's: doorID = 7; lightID = 17; -- time to enter, longer time will detect as another situation, like: cleaning timeToEnter = 10; local light = fibaro:getValue(lightID, 'value'); local door = fibaro:getValue(doorID, 'value'); local armed, lastArmed = fibaro:get(doorID, 'armed'); local trigger = fibaro:getSourceTrigger(); if (fibaro:countScenes()>1) then fibaro:debug('Kill second scene!'); fibaro:abort(); end if (trigger['type']=='property') then -- door trigger if (trigger['deviceID']==tostring(doorID)) then -- door opened if (door=='1') then fibaro:debug('Door opened.'); if (armed=='0') then fibaro:call(lightID, 'turnOn'); fibaro:call(doorID, 'setArmed', '1'); fibaro:call(doorID, 'setArmed', '0'); fibaro:debug('Light on!'); end -- door closed elseif (door=='0') then fibaro:debug('Door closed.'); if (armed=='1' or (os.time()-lastArmed)>=timeToEnter) then fibaro:call(lightID, 'turnOff'); fibaro:call(doorID, 'setArmed', '0'); fibaro:debug('Light off, room empty!'); else fibaro:call(doorID, 'setArmed', '1'); fibaro:debug('Someone inside!'); end end -- light manual elseif (trigger['deviceID']==tostring(lightID) and (os.time()-lastArmed)>0) then -- light manual off if (light=='0') then if (door=='1') then -- when door are opened fibaro:call(doorID, 'setArmed', '1'); else -- when door are closed fibaro:call(doorID, 'setArmed', '0'); end fibaro:debug('Light manual off!'); -- light manual on elseif (light=='1') then fibaro:call(doorID, 'setArmed', '1'); fibaro:debug('Light manual on, arming...'); end end end
  18. Simple scene to detect motion direction detection. First detecting motion and then door opening to turn on a light. Can ofcourse also be turned the other way... --[[--[[ %% properties 26 value %% globals --]] local milisec = 5000; local IDFirstDetection = 26; local IDSecondDetection = 42; local startSource = fibaro:getSourceTrigger(); if ( ( tonumber(fibaro:getValue(IDFirstDetection, "value")) > 0 ) or startSource["type"] == "other" ) then if ( tonumber(fibaro:getValue(IDSecondDetection, "value")) > 0 ) then --You can choose to also turn on the device here ... -- Or even to turn off devices in the room you just left fibaro:debug("door is already open"); else fibaro:debug("Door is closed, waiting for it to open"); while milisec > 0 do if ( tonumber(fibaro:getValue(IDSecondDetection, "value")) > 0 ) then fibaro:debug("door opened"); fibaro:call(179, "turnOn"); break; end fibaro:sleep(100); milisec=milisec - 100; fibaro:debug("door not opened yet. waiting" .. milisec ); end end end Works like a charm in combination with the Auto lights of Virtual device. Any suggetions to make it even better? For instance for when the second motion or door sensor is already triggered? Or maybe for when you have 3 detectors, or two different rooms to go into? Got a nice alternative: --[[ %% properties 26 value %% globals --]] local milisec = 6000; local IDFirstDetection = 26; local IDSecondDetection = 42; local startSource = fibaro:getSourceTrigger(); if ( ( tonumber(fibaro:getValue(IDFirstDetection, "value")) > 0 ) or startSource["type"] == "other" ) then if ( tonumber(fibaro:getValue(IDSecondDetection, "value")) > 0 ) then fibaro:debug("door is already open"); else fibaro:call(180, "turnOn") fibaro:debug("light turned on. Probalby entering the room soon."); fibaro:debug("Door is closed, waiting for it to open"); while milisec > 0 do if ( tonumber(fibaro:getValue(IDSecondDetection, "value")) > 0 ) then fibaro:debug("door opened"); --if fibaro:getGlobalValue("Time Of Day") == "Evening" then -- fibaro:call(180, "turnOn") --end -- if (fibaro:getGlobalValue("SleepState") == "Sleeping") then -- fibaro:call(74, "setValue", "60") -- end break; end fibaro:sleep(100); milisec=milisec - 100; if (milisec == 0 ) then fibaro:debug("Door never opend, turning off the device again") fibaro:call(180, "turnOff") end fibaro:debug("door not opened yet. waiting" .. milisec ); end end end In the last one, it actually turns the light on with the first motion detection. When the second is also detected it will leave the light on. When no motion is detected it will turn the light off. This means that you can use it for a hall way. It will turn the lights on in 3 rooms, the room you go into will stay on, the other rooms will turn off. Have to build in a check if the light wasn't already on... other wise when someone else is in the room, the light will be turned off
×
×
  • Create New...