Compare commits

...

184 Commits

Author SHA1 Message Date
Michael Teeuw
b508a629e8 Merge pull request #1632 from MichMich/fix-2.7.1
Fix package.json version number.
2019-04-02 09:50:36 +02:00
Michael Teeuw
abb0dadead Fix package.json version number. 2019-04-02 09:34:42 +02:00
Michael Teeuw
e6fb18df56 Merge pull request #1627 from MichMich/develop
Release 2.7.0
2019-04-01 21:54:05 +02:00
Michael Teeuw
43ba13f3bc Prepare 2.8.0-develop. 2019-04-01 21:26:39 +02:00
Michael Teeuw
ba705f5563 Fix Lint Issue. 2019-04-01 20:55:24 +02:00
Michael Teeuw
34e188ec1f Typo. 2019-04-01 20:48:30 +02:00
Michael Teeuw
b0d97dd170 Prepare for release. 2019-04-01 20:47:07 +02:00
Michael Teeuw
7caeae61f5 Merge pull request #1625 from qistoph/fix_weather_title
Update current weather header only if not undefined
2019-04-01 20:36:37 +02:00
Chris van Marle
416ace4c86 Update current weather header only if not undefined 2019-03-29 13:15:58 +01:00
Chris van Marle
979041ee91 Fix typo in variable name fetchedLocationName 2019-03-29 13:13:56 +01:00
Michael Teeuw
f0939b8af5 Merge pull request #1622 from JasMich/develop
Develop
2019-03-28 19:12:17 +01:00
Jasper Michalke
d7a7002bdd Finally added all required files for Klingon translations 2019-03-28 14:57:45 +01:00
Jasper Michalke
d9601de075 Update translations.js
Added Klingon translations file to translations list
2019-03-28 14:55:01 +01:00
Jasper Michalke
ef570558cf Update CHANGELOG.md 2019-03-28 14:53:28 +01:00
Michael Teeuw
db3e81408f Merge pull request #1618 from dgburr/newsfeed-article-info-request
Add support for the ARTICLE_INFO_REQUEST notification
2019-03-28 12:45:19 +01:00
Michael Teeuw
e8771cdea8 Merge branch 'develop' into newsfeed-article-info-request 2019-03-28 12:11:06 +01:00
Michael Teeuw
057eab2173 Merge pull request #1619 from dgburr/changelog-fix
Fix changelog
2019-03-28 12:09:53 +01:00
Michael Teeuw
e2a7024eeb Merge pull request #1620 from garyray-k/master
Spelling correction in README.md
2019-03-28 12:09:35 +01:00
Michael Teeuw
4650986dfa Merge pull request #1621 from kolbyjack/feature/calendar-name
Add name property to calendars
2019-03-28 12:09:09 +01:00
Jon Kolb
868b5e4617 Add name property to calendars
When consuming CALENDAR_EVENTS broadcasts, it is useful for other
modules to be able to identify which calendar a specific event
came from, for filtering/display purposes.
2019-03-26 19:51:44 -04:00
Gary Krause
f12860c7b1 Spelling correction in README.md
small spelling correction.
2019-03-25 14:07:53 -04:00
Daniel Burr
8f751812a6 The note which I added to the changelog in commit 80eef2ab8c was in the 2.6.0 section instead of 2.7.0 2019-03-25 01:19:00 +01:00
Daniel Burr
07a5092eb3 Add note to changelog 2019-03-25 01:13:02 +01:00
Daniel Burr
29c9c92ba6 Add support for the ARTICLE_INFO_REQUEST notification
Upon reception of an ARTICLE_INFO_REQUEST notification, newsfeed will
respond with the notification ARTICLE_INFO_RESPONSE, containing the
fields 'title', 'source', 'date', 'desc' and 'url'.
2019-03-25 01:08:59 +01:00
Michael Teeuw
edfa327158 Merge pull request #1602 from qistoph/develop
Notifications delay time and background color
2019-03-19 09:36:24 +01:00
Michael Teeuw
869a6e66cc Merge pull request #1611 from ZakarFin/node-upgrade
Node.js upgrade to 10.x (installer)
2019-03-19 09:36:13 +01:00
Sami Mäkinen
36abbfc048 Changelog 2019-03-18 23:12:44 +02:00
Sami Mäkinen
cfc3e6d2f4 Merge branch 'master' into develop 2019-03-18 22:51:23 +02:00
Sami Mäkinen
e38dbee6a6 Node 9 -> 10 (LTS) 2019-03-18 22:23:10 +02:00
Michael Teeuw
68a7c857c0 Merge pull request #1610 from dgburr/documentation-fix
Fix documentation of `useKMPHwind` option in currentweather
2019-03-18 17:09:04 +01:00
Daniel Burr
80eef2ab8c Fix documentation of useKMPHwind option in currentweather 2019-03-18 16:23:03 +01:00
Michael Teeuw
1d652aa746 Merge branch 'develop' into develop 2019-03-18 16:08:13 +01:00
Michael Teeuw
b07c43aa36 Merge pull request #1599 from rejas/use_getHeader
Use getHeader instead of data.header
2019-03-18 16:04:45 +01:00
Chris van Marle
3880c8dc2c Restyle notification colors 2019-03-14 14:11:14 +01:00
Chris van Marle
c0ab2ac297 Support timer in notifications too 2019-03-14 14:11:10 +01:00
Veeck
de684dcb63 Fix typos in jsdoc 2019-03-11 14:03:01 +02:00
Veeck
29ef1db86b Remove whitespace 2019-03-08 11:33:02 +01:00
Veeck
5dfd8a61be Update changelog 2019-03-08 11:29:48 +01:00
Veeck
358e2b3ccf Use getHeader instead of data.header when creating the DOM 2019-03-08 11:25:38 +01:00
Michael Teeuw
4203065a06 Merge pull request #1590 from vincep5/develop
Adding new weather provider for weather.gov
2019-03-07 09:18:40 +01:00
vincep5
bc4e0190a0 readme formatting 2019-03-06 21:33:13 -06:00
Michael Teeuw
dd7004cbc9 Merge pull request #1598 from rejas/more_verbose_error_message
More verbose error message when config.js is broken
2019-03-06 11:48:45 +01:00
Veeck
bdc5c8f620 Fix typos in changelog 2019-03-06 10:02:01 +01:00
Veeck
02d36e22ee Show more verbose error message on console if the config is malformed 2019-03-06 10:01:44 +01:00
Michael Teeuw
331e8c4aa6 Merge pull request #1594 from rejas/patch-1
Updated modernizr code in alert module
2019-03-05 10:26:47 +01:00
Veeck
d622277c11 Updated modernizr code to latest version 2019-03-02 08:40:20 +01:00
Veeck
8f781ea4ab Small typo fix in link 2019-03-02 08:30:08 +01:00
vincep5
ebc1e5bf12 tidy up code for weather 2019-02-27 09:09:37 -06:00
Michael Teeuw
ce9a61622e Merge pull request #1592 from MichMich/revert-1564-develop
Revert "Added autoLocation and autoTimezone option for weather modules and clock respectively."
2019-02-27 13:41:13 +01:00
Michael Teeuw
e4891e699f Revert "Added autoLocation and autoTimezone option for weather modules and clock respectively." 2019-02-27 13:33:14 +01:00
vincep5
d8765578c8 weather.gov N arrow 2019-02-26 14:51:09 -06:00
vincep5
3a034ecec8 Adding new weather provider for weather.gov 2019-02-26 14:06:00 -06:00
vin p
a3dea45089 Merge pull request #4 from MichMich/develop
Develop
2019-02-26 13:59:38 -06:00
Michael Teeuw
de99c8a5e4 Merge pull request #1589 from hudashot/calendar
Regularly trigger ADD_CALENDAR to ensure calendar fetcher is running
2019-02-26 11:17:30 +01:00
hudashot
d3b8dbeea0 Regularly trigger ADD_CALENDAR to ensure calendar fetcher is running 2019-02-26 08:12:02 +00:00
Michael Teeuw
cff2f64155 Merge pull request #1586 from Tom-Hirschberger/feature/alert-fontawesome
Feature/alert fontawesome
2019-02-24 19:58:44 +01:00
Thomas Hirschberger
7b8de35405 Update CHANGELOG.md 2019-02-24 11:55:46 +01:00
Tom Hirschberger
02ae0df2cc add font-awesome.css to styles of alert.js 2019-02-24 11:48:14 +01:00
Michael Teeuw
b386cea69d Merge pull request #1582 from mdobsovic/develop
Slovak translation added
2019-02-23 12:09:48 +01:00
Michal Dobsovic
758ffb75a9 Added sk to translations.js 2019-02-23 10:37:24 +01:00
Michal Dobsovic
78fbc7f392 Modified CHANGELOG.md 2019-02-20 22:15:24 +01:00
Michal Dobsovic
9c58472576 Merge branch 'develop' of https://github.com/mdobsovic/MagicMirror into develop 2019-02-20 22:07:19 +01:00
Michal Dobsovic
f8c4afc228 Slovak translation added 2019-02-20 22:02:42 +01:00
Michael Teeuw
b169d65619 Merge pull request #1577 from sdetweil/develop
fix relative date fulldate events to use start of day to start of day diff… issue 1572
2019-02-19 15:47:57 +01:00
Michael Teeuw
9bf0d4f804 Merge pull request #1580 from lavolp3/lavolp3-patch-1
Changed defaut dateEndFormat
2019-02-19 15:47:41 +01:00
Dirk
4443f57f8a Update CHANGELOG.md 2019-02-19 14:10:17 +01:00
Sam Detweiler
ea5d8590d5 Merge branch 'develop' of https://github.com/sdetweil/MagicMirror into develop 2019-02-19 07:08:46 -06:00
sam detweiler
5d5feb4c71 Merge pull request #1 from MichMich/develop
Develop
2019-02-19 07:08:13 -06:00
Dirk
feb5351ec3 changed default calendarEndDate to "LT"
changed default calendarEndDate to "LT" to show local times for event end times. 
Can still be set to a different value by the user
2019-02-19 14:07:01 +01:00
Sam Detweiler
7630c25ef3 add future date offset correction for emergency date values in absolute mode 2019-02-19 07:06:22 -06:00
Michael Teeuw
24238094e5 Fix url. 2019-02-19 13:43:23 +01:00
Michael Teeuw
7cc9a03db8 Merge pull request #1578 from lavolp3/splitDates
Add "sliceMultiDayEvents" option in calendar module
2019-02-19 09:13:33 +01:00
Dirk
2b2e8508d9 Update calendar.js
Small updates for travis cr check
2019-02-18 22:38:28 +01:00
Dirk
a70716f225 Merge branch 'splitDates' of https://github.com/lavolp3/MagicMirror into splitDates 2019-02-18 21:11:58 +01:00
Dirk
d9fcc46994 included split function to split multiday events 2019-02-18 21:11:24 +01:00
Dirk
2d8acec6f0 Update CHANGELOG.md 2019-02-18 21:04:56 +01:00
Dirk
cd06d8c63a Merge pull request #5 from MichMich/develop
Develop
2019-02-18 21:02:46 +01:00
Sam Detweiler
a06ca55107 fix relative date fulldate events to use start of dat to start of day difference, fix extra space in changelog 2019-02-18 07:30:46 -06:00
Sam Detweiler
9686a9ba77 fix relative date fulldate events to use start of dat to start of day difference 2019-02-18 07:18:07 -06:00
Michael Teeuw
f7f4043ccd Merge pull request #1571 from kolbyjack/develop
Fix null dereference in moduleNeedsUpdate when the module isn't visible
2019-02-15 13:57:24 +01:00
Michael Teeuw
b7b55173a6 Merge pull request #1573 from vincep5/develop
weather module adjustments for rain and snow
2019-02-15 13:56:58 +01:00
Michael Teeuw
954253c7e2 Remove Slack. 2019-02-15 11:15:06 +01:00
vincep5
cbe4d2cd7f weather module adjustments for rain and snow 2019-02-14 13:00:40 -06:00
vin p
40101129b5 Merge pull request #3 from MichMich/develop
Develop
2019-02-14 12:20:52 -06:00
Michael Teeuw
4bb32c6d09 Merge pull request #1514 from fwitte/features/weather_forecast_and_forecast_daily_support
Add forecast and forecast/daily support to new weather module
2019-02-14 17:41:10 +01:00
Michael Teeuw
6e09ceeda6 Merge branch 'develop' into features/weather_forecast_and_forecast_daily_support 2019-02-14 17:34:08 +01:00
fwitte
d6a6a53623 updated weather icon display 2019-02-14 16:48:45 +01:00
Michael Teeuw
4a97052708 Fix linting error. 2019-02-14 13:50:16 +01:00
Jon Kolb
3a4902ad4a Fix null dereference in moduleNeedsUpdate when the module isn't visible 2019-02-14 00:06:45 +00:00
Michael Teeuw
77d14bc218 Add donation link. 2019-02-13 16:12:46 +01:00
Michael Teeuw
1d2a39a855 Merge pull request #1564 from jacob-ebey/develop
Added autoLocation and autoTimezone option for weather modules and clock respectively.
2019-02-13 09:46:25 +01:00
Michael Teeuw
98b53b6b3d Merge branch 'develop' into develop 2019-02-13 09:38:15 +01:00
Michael Teeuw
0148d8beaf Merge pull request #1565 from AnthonyBuisset/fix/calendar
Fix exdate handling when multiple values are specified (comma separated)
2019-02-13 09:37:06 +01:00
Michael Teeuw
5bfd84d3be Merge pull request #1567 from stefsims/patch-2
Added danish translation
2019-02-13 09:36:11 +01:00
Michael Teeuw
351eb95feb Merge pull request #1566 from stefsims/patch-1
Update da.json
2019-02-13 09:35:53 +01:00
stefsims
56788f0933 Update CHANGELOG.md
Added danish translation
2019-02-11 09:02:42 +01:00
stefsims
017a376616 Update da.json
Added FEELS and WEEK
2019-02-11 08:59:16 +01:00
Anthony Buisset
c5888cec66 Fix exdate handling when multiple values are specified (comma separated) 2019-02-10 16:30:12 +01:00
Jacob Ebey
3d5ad29eac - Removed trailing space 2019-02-09 13:51:23 -08:00
Jacob Ebey
c608636b7a - Added autoTimezone property to the clock 2019-02-09 13:41:42 -08:00
Jacob Ebey
1a97107b2d - Converted indentation to tabs. 2019-02-09 12:49:47 -08:00
Jacob Ebey
5ca3fbeaea Added autoLocation option for weather modules. 2019-02-09 12:42:42 -08:00
Michael Teeuw
44896db668 Merge pull request #1554 from roramirez/replace-console-log-none
serveronly: Replace the console.log of none for a \n new line
2019-01-27 11:22:17 +01:00
Rodrigo Ramírez Norambuena
12efb87a23 serveronly: Replace the console.log of none for a \n new line 2019-01-26 14:42:15 -05:00
Michael Teeuw
9181be86ba Merge pull request #1553 from CriticalPoint/patch-1
Updated README
2019-01-25 09:56:25 +01:00
Mike
053b01e036 Updated README
Scanned through it and corrected some spelling mistakes, nothing that affects the core purpose of the document.
2019-01-25 07:50:24 +00:00
Michael Teeuw
86041d0968 Merge pull request #1541 from amcolash/trim_calendar_events
Add in vertical cutting for long calendar event titles
2019-01-23 13:38:19 +01:00
Michael Teeuw
bd87f63e91 Merge pull request #1542 from vincep5/develop
current.njk JS error and Loading string
2019-01-23 13:37:25 +01:00
Dirk
b79b49e8f3 Merge pull request #3 from MichMich/master
updated from master
2019-01-23 10:36:05 +01:00
Andrew McOlash
a0dde39d97 Fix braces for if check 2019-01-21 00:47:53 -08:00
vincep5
2e03868021 current.njk JS error and Loading string 2019-01-17 08:54:16 -06:00
vin p
29384c2ba3 Merge pull request #2 from MichMich/develop
Develop
2019-01-17 08:48:16 -06:00
Andrew McOlash
320743ab8d fix spacing 2019-01-16 22:53:28 -08:00
Andrew McOlash
399e171083 Add in cutting of long vertical titles 2019-01-16 22:51:44 -08:00
Michael Teeuw
184164b677 Merge pull request #1535 from fdahms/develop
forgot one sudo in installation script
2019-01-15 12:48:11 +01:00
fdahms
6d9675a299 forgot one sudo 2019-01-13 20:07:20 +01:00
Michael Teeuw
91e8ce62d4 Merge pull request #1534 from PalatinCoder/patch-1
fix: only show repeating count if the event is actually repeating
2019-01-13 16:36:45 +01:00
Jan Syring-Lingenfelder
06e641015f docs: update changelog 2019-01-13 16:25:57 +01:00
Jan Syring-Lingenfelder
1c83059482 fix: only show repeating count if the event is actually repeating 2019-01-13 16:18:52 +01:00
Michael Teeuw
90b24d824a Merge pull request #1531 from fdahms/develop
Fixing raspbian installation script
2019-01-13 11:58:30 +01:00
Michael Teeuw
62457d0e48 Merge pull request #1532 from oddswop/patch-1
Update README.md - just fixing a typo :)
2019-01-13 11:57:27 +01:00
Yvonne
90c96f7479 Update README.md 2019-01-13 09:26:37 +11:00
fdahms
f87adebe41 Fixing raspbian installer
* fixing issue #1377
* fixing problem with old node installation from fresh raspbian
* add feature for disable screen saver
2019-01-12 18:11:48 +01:00
fdahms
8f24cc8d13 editing CHANGELOG 2019-01-12 18:06:52 +01:00
Michael Teeuw
992802d196 Merge pull request #1525 from ianperrin/develop
Fix conflict between font awesome versions as per #1522
2019-01-10 13:50:14 +01:00
Ian
8546d6730c Update CHANGELOG.md 2019-01-10 12:44:35 +00:00
Ian
0092289105 revert font awesome reference 2019-01-09 21:38:07 +00:00
Ian
7c3923ad00 Use Font Awesome 5 (with backwards compatibility) for all modules 2019-01-09 21:32:43 +00:00
Ian
ef82039401 Allow multiple css to be included for one vendor 2019-01-09 21:29:49 +00:00
Ian
b01b9758e0 remove Font Awesome 4 dependency 2019-01-09 21:24:14 +00:00
vin p
88b00f689b Merge pull request #1 from MichMich/develop
Develop
2019-01-08 20:55:46 -06:00
Michael Teeuw
0a340d5d57 Merge pull request #1512 from fwitte/features/currentweather_weatherforecost_degreesign
still show degree sign if degreeLabel/scale is false
2019-01-08 09:36:26 +01:00
Michael Teeuw
50545a83b8 Merge pull request #1515 from andogit7/andogit7-MM-develop
Andogit7 mm develop
2019-01-08 09:34:50 +01:00
Michael Teeuw
4a57ff40d8 Merge pull request #1518 from fwitte/features/fade_forecast_and_maxnumberdays
Features/fade forecast and maxnumberdays
2019-01-08 09:33:26 +01:00
Michael Teeuw
0238455a5a Merge pull request #1521 from Bardo98/patch-1
Added Italian translation of "FEELS"
2019-01-08 09:10:22 +01:00
Bardo98
a53e963001 Merge pull request #1 from Bardo98/patch-2
Update CHANGELOG.md
2019-01-07 22:19:01 +01:00
Bardo98
984608e23f Added Italian translation of "FEELS" 2019-01-07 22:05:26 +01:00
Bardo98
f680c83d2d Update CHANGELOG.md 2019-01-07 21:55:18 +01:00
fwitte
a79e51c76f updated +CHANGELOG 2019-01-07 08:51:17 +01:00
fwitte
2dfb349609 fixed missing last day display in forecast/hourly 2019-01-07 08:19:50 +01:00
fwitte
766f21b525 adjusted default values 2019-01-06 12:34:44 +01:00
fwitte
733dfa1467 adjusted README 2019-01-06 12:34:27 +01:00
fwitte
63aa840b55 replaced tabs with spaces 2019-01-06 12:30:26 +01:00
fwitte
8b2d544576 added fade and maxnumberofdays options for forecast 2019-01-06 12:24:26 +01:00
fwitte
d6046d2422 simplified fetchForecastHourly function 2019-01-06 10:24:16 +01:00
fwitte
409939360f do not show 0 mm rain value 2019-01-06 10:23:15 +01:00
andogit7
1d21f39fbc Update CHANGELOG.md 2019-01-05 17:09:15 +00:00
andogit7
a477140a4b Update CHANGELOG.md 2019-01-05 17:08:55 +00:00
andogit7
1bbf2d8ce6 Update clock.js 2019-01-05 17:04:33 +00:00
fwitte
40a65eec51 adjusted CHANGELOG 2019-01-05 17:16:50 +01:00
fwitte
8431ebf2e8 adjusted README 2019-01-05 17:16:37 +01:00
fwitte
bdcc0c5373 another typo fix 2019-01-05 17:16:19 +01:00
fwitte
9cbf331533 fixed typo in daily data fetcher 2019-01-05 16:56:47 +01:00
fwitte
77640714cc adjusted openweathermap module to work with /forecast and forecast/daily 2019-01-05 16:54:45 +01:00
fwitte
9457d95c3f Merge remote-tracking branch 'origin' into develop 2019-01-05 15:27:05 +01:00
fwitte
c2ff949f2d adjusted CHANGELOG 2019-01-05 13:14:10 +01:00
fwitte
ba8685a122 readded degreesign 2019-01-05 13:13:53 +01:00
Francesco Witte
55464ed0dd Merge pull request #1 from MichMich/develop
Develop
2019-01-05 12:59:23 +01:00
Michael Teeuw
fdf3691c87 Merge pull request #1510 from fewieden/feature/weather-module-improvements
Fixed issues with the new weather module
2019-01-05 12:29:12 +01:00
fewieden
aa6699cf3e link issues to changelog 2019-01-05 10:33:58 +01:00
fewieden
b79b48baac link issues to changelog 2019-01-05 10:32:09 +01:00
fewieden
5d22dbd99e changelog 2019-01-05 10:26:13 +01:00
Michael Teeuw
4686bb5584 Merge pull request #1509 from shbatm/bug-fix
Fixes Incomplete fix for MichMich/MagicMirror#1507
2019-01-05 07:09:35 +01:00
shbatm
1f62b8f0b6 Update node_helper.js 2019-01-04 18:12:12 -06:00
fewieden
5759ed3728 implemented config option decimal symbol, align indoor elements vertical, add humidity support to nunjuck unit filter, do not display degree symbol for kelvin 2019-01-04 20:14:28 +01:00
fewieden
827fbfb78f dimmed loading indicator for weather forecast 2019-01-04 20:14:28 +01:00
fewieden
dc363de610 fix weather forecast table height 2019-01-04 20:14:28 +01:00
shbatm
b9d6a235e3 Fixes Incomplete fix for MichMich/MagicMirror#1507 2019-01-04 12:37:58 -06:00
Michael Teeuw
ebc57fe494 Merge pull request #1507 from shbatm/bug-fix
Error handling for bad git data in updatenotification
2019-01-04 17:00:27 +01:00
Michael Teeuw
e224ec4ae0 Merge branch 'develop' into bug-fix 2019-01-04 17:00:18 +01:00
Michael Teeuw
a5da347177 Merge pull request #1506 from fwitte/fwitte/weather_forecast_daily_openweather
Fix openweather forecast in new weather module, fetch daily data
2019-01-04 16:59:35 +01:00
shbatm
a257b15f86 Error handling for bad git data in updatenotification
Update CHANGELOG
2019-01-04 09:23:10 -06:00
Michael Teeuw
a70cc53d82 Merge branch 'develop' into fwitte/weather_forecast_daily_openweather 2019-01-04 13:04:02 +01:00
fwitte
1df2de9202 updated README 2019-01-04 12:34:29 +01:00
fwitte
9e394ea349 updated CHANGELOG 2019-01-04 12:34:12 +01:00
fwitte
b55685d610 added comments 2019-01-04 12:13:39 +01:00
fwitte
2156aac046 fixed typos, fetching forecast parameters by day 2019-01-04 12:07:02 +01:00
Michael Teeuw
6914465e3d Remove "Focus" to pass test. 2019-01-03 16:42:31 +01:00
Michael Teeuw
f3847ec6f3 Bump Node version to 8. 2019-01-03 16:35:30 +01:00
Michael Teeuw
e1fe8d1d89 Bump Electron to v3.0.13 - Issue: #1500 2019-01-03 16:04:33 +01:00
Michael Teeuw
675c937a4a Merge pull request #1505 from fwitte/fwitte/change_temperature_unit_display
Remove degree symbol for Kelvin scale
2019-01-03 15:25:24 +01:00
fwitte
c8f53bdf8e updated CHANGELOG.md 2019-01-03 12:35:52 +01:00
fwitte
3541d5adde removed degree symbol display for Kelvin scale, match source code in currentweather and weatherforecast 2019-01-03 12:06:52 +01:00
Michael Teeuw
b52da7c9fc Prepare for 2.7.0 dev branch. 2019-01-01 17:15:37 +01:00
46 changed files with 1301 additions and 599 deletions

View File

@@ -1,6 +1,6 @@
language: node_js
node_js:
- "7"
- "8"
before_script:
- yarn danger ci
- npm install grunt-cli -g

View File

@@ -5,6 +5,65 @@ This project adheres to [Semantic Versioning](http://semver.org/).
---
❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/donate) With your help we can continue to improve the MagicMirror² core.
## [2.7.1] - 2019-04-02
Fixed `package.json` version number.
## [2.7.0] - 2019-04-01
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues running Electron, make sure your [Raspbian is up to date](https://www.raspberrypi.org/documentation/raspbian/updating.md).
### Added
- Italian translation for "Feels"
- Basic Klingon (tlhIngan Hol) translations
- Disabled the screensaver on raspbian with installation script
- Added option to truncate the number of vertical lines a calendar item can span if `wrapEvents` is enabled.
- Danish translation for "Feels" and "Weeks"
- Added option to split multiple day events in calendar to separate numbered events
- Slovakian translation
- Alerts now can contain Font Awesome icons
- Notifications display time can be set in request
- Newsfeed: added support for `ARTICLE_INFO_REQUEST` notification
- Add `name` config option for calendars to be sent along with event broadcasts
### Updated
- Bumped the Electron dependency to v3.0.13 to support the most recent Raspbian. [#1500](https://github.com/MichMich/MagicMirror/issues/1500)
- Updated modernizr code in alert module, fixed a small typo there too
- More verbose error message on console if the config is malformed
- Updated installer script to install Node.js version 10.x
### Fixed
- Fixed temperature displays in currentweather and weatherforecast modules [#1503](https://github.com/MichMich/MagicMirror/issues/1503), [#1511](https://github.com/MichMich/MagicMirror/issues/1511).
- Fixed unhandled error on bad git data in updatenotification module [#1285](https://github.com/MichMich/MagicMirror/issues/1285).
- Weather forecast now works with openweathermap in new weather module. Daily data are displayed, see issue [#1504](https://github.com/MichMich/MagicMirror/issues/1504).
- Fixed analogue clock border display issue where non-black backgrounds used (previous fix for issue 611)
- Fixed compatibility issues caused when modules request different versions of Font Awesome, see issue [#1522](https://github.com/MichMich/MagicMirror/issues/1522). MagicMirror now uses [Font Awesome 5 with v4 shims included for backwards compatibility](https://fontawesome.com/how-to-use/on-the-web/setup/upgrading-from-version-4#shims).
- Installation script problems with raspbian
- Calendar: only show repeating count if the event is actually repeating [#1534](https://github.com/MichMich/MagicMirror/pull/1534)
- Calendar: Fix exdate handling when multiple values are specified (comma separated)
- Calendar: Fix relative date handling for fulldate events, calculate difference always from start of day [#1572](https://github.com/MichMich/MagicMirror/issues/1572)
- Fix null dereference in moduleNeedsUpdate when the module isn't visible
- Calendar: Fixed event end times by setting default calendarEndTime to "LT" (Local time format). [#1479]
- Calendar: Fixed missing calendar fetchers after server process restarts [#1589](https://github.com/MichMich/MagicMirror/issues/1589)
- Notification: fixed background color (was white text on white background)
- Use getHeader instead of data.header when creating the DOM so overwriting the function also propagates into it
- Fix documentation of `useKMPHwind` option in currentweather
### New weather module
- Fixed weather forecast table display [#1499](https://github.com/MichMich/MagicMirror/issues/1499).
- Dimmed loading indicator for weather forecast.
- Implemented config option `decimalSymbol` [#1499](https://github.com/MichMich/MagicMirror/issues/1499).
- Aligned indoor values in current weather vertical [#1499](https://github.com/MichMich/MagicMirror/issues/1499).
- Added humidity support to nunjuck unit filter.
- Do not display degree symbol for temperature in Kelvin [#1503](https://github.com/MichMich/MagicMirror/issues/1503).
- Weather forecast now works with openweathermap for both, `/forecast` and `/forecast/daily`, in new weather module. If you use the `/forecast`-weatherEndpoint, the hourly data are converted to daily data, see issues [#1504](https://github.com/MichMich/MagicMirror/issues/1504), [#1513](https://github.com/MichMich/MagicMirror/issues/1513).
- Added fade, fadePoint and maxNumberOfDays properties to the forecast mode [#1516](https://github.com/MichMich/MagicMirror/issues/1516)
- Fixed Loading string and decimalSymbol string replace [#1538](https://github.com/MichMich/MagicMirror/issues/1538)
- Show Snow amounts in new weather module [#1545](https://github.com/MichMich/MagicMirror/issues/1545)
- Added weather.gov as a new weather provider for US locations
## [2.6.0] - 2019-01-01
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues updating, make sure you are running the latest version of Node.
@@ -12,6 +71,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### ✨ Experimental ✨
- New default [module weather](modules/default/weather). This module will eventually replace the current `currentweather` and `weatherforecast` modules. The new module is still pretty experimental, but it's included so you can give it a try and help us improve this module. Please give us you feedback using [this forum post](https://forum.magicmirror.builders/topic/9335/default-weather-module-refactoring).
A huge, huge, huge thanks to user @fewieden for all his hard work on the new `weather` module!
### Added
- Possibility to add classes to the cell of symbol, title and time of the events of calendar.
- Font-awesome 5, still has 4 for backwards compatibility.
@@ -60,7 +121,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Fixed gzip encoded calendar loading issue #1400.
- Mixup between german and spanish translation for newsfeed.
- Fixed close dates to be absolute, if no configured in the config.js - module Calendar
- Fixed the UpdateNotification module message about new commits in the repository, so they can be correctly localized in singular and plural form.
- Fixed the updatenotification module message about new commits in the repository, so they can be correctly localized in singular and plural form.
- Fix for weatherforecast rainfall rounding [#1374](https://github.com/MichMich/MagicMirror/issues/1374)
- Fix calendar parsing issue for Midori on RasperryPi Zero w, related to issue #694.
- Fix weather city ID link in sample config
@@ -210,7 +271,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Add `clientonly` script to start only the electron client for a remote server.
- Add symbol and color properties of event when `CALENDAR_EVENTS` notification is broadcasted from `default/calendar` module.
- Add `.vscode/` folder to `.gitignore` to keep custom Visual Studio Code config out of git.
- Add unit test the capitalizeFirstLetter function of newfeed module.
- Add unit test the capitalizeFirstLetter function of newsfeed module.
- Add new unit tests for function `shorten` in calendar module.
- Add new unit tests for function `getLocaleSpecification` in calendar module.
- Add unit test for js/class.js.
@@ -231,7 +292,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Set version of the `express-ipfilter` on 0.3.1.
### Fixed
- Fixed issue with incorrect allignment of analog clock when displayed in the center column of the MM.
- Fixed issue with incorrect alignment of analog clock when displayed in the center column of the MM.
- Fixed ipWhitelist behaviour to make empty whitelist ([]) allow any and all hosts access to the MM.
- Fixed issue with calendar module where 'excludedEvents' count towards 'maximumEntries'.
- Fixed issue with calendar module where global configuration of maximumEntries was not overridden by calendar specific config (see module doc).
@@ -255,7 +316,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Add unit test calendar_modules function capFirst.
- Add test for check if exists the directories present in defaults modules.
- Add support for showing wind direction as an arrow instead of abbreviation in currentWeather module.
- Add support for writing translation fucntions to support flexible word order
- Add support for writing translation functions to support flexible word order
- Add test for check if exits the directories present in defaults modules.
- Add calendar option to set a separate date format for full day events.
- Add ability for `currentweather` module to display indoor temperature via INDOOR_TEMPERATURE notification
@@ -274,7 +335,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Fix double message about port when server is starting
- Corrected Swedish translations for TODAY/TOMORROW/DAYAFTERTOMORROW.
- Removed unused import from js/electron.js
- Made calendar.js respect config.timeFormat irrespecive of locale setting.
- Made calendar.js respect config.timeFormat irrespective of locale setting.
- Fixed alignment of analog clock when a large calendar is displayed in the same side bar.
## [2.1.1] - 2017-04-01
@@ -292,7 +353,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Added `DAYAFTERTOMORROW`, `UPDATE_NOTIFICATION` and `UPDATE_NOTIFICATION_MODULE` to Finnish translations.
- Run `npm test` on Travis automatically.
- Show the splash screen image even when is reboot or halted.
- Added some missing translaton strings in the sv.json file.
- Added some missing translation strings in the sv.json file.
- Run task jsonlint to check translation files.
- Restructured Test Suite.
@@ -309,12 +370,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Option to use RegExp in Calendar's titleReplace.
- Hungarian Translation.
- Icelandic Translation.
- Add use a script to prevent when is run by SSH session set DISPLAY enviroment.
- Enable ability to set configuration file by the enviroment variable called MM_CONFIG_FILE.
- Add use a script to prevent when is run by SSH session set DISPLAY environment.
- Enable ability to set configuration file by the environment variable called MM_CONFIG_FILE.
- Option to give each calendar a different color.
- Option for colored min-temp and max-temp.
- Add test e2e helloworld.
- Add test e2e enviroment.
- Add test e2e environment.
- Add `chai-as-promised` npm module to devDependencies.
- Basic set of tests for clock module.
- Run e2e test in Travis.
@@ -332,10 +393,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Added tests for Translations, dev argument, version, dev console.
- Added test anytime feature compliments module.
- Added test ipwhitelist configuration directive.
- Added test for calendar module: default, basic-auth, backward compability, fail-basic-auth.
- Added test for calendar module: default, basic-auth, backward compatibility, fail-basic-auth.
- Added meta tags to support fullscreen mode on iOS (for server mode)
- Added `ignoreOldItems` and `ignoreOlderThan` options to the News Feed module
- Added test for MM_PORT enviroment variable.
- Added test for MM_PORT environment variable.
- Added a configurable Week section to the clock module.
### Fixed
@@ -347,7 +408,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Module currentWeather: check if temperature received from api is defined.
- Fix an issue with module hidden status changing to `true` although lock string prevented showing it.
- Fix newsfeed module bug (removeStartTags)
- Fix when is set MM_PORT enviroment variable.
- Fix when is set MM_PORT environment variable.
- Fixed missing animation on `this.show(speed)` when module is alone in a region.
## [2.1.0] - 2016-12-31
@@ -369,8 +430,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Calendar module now broadcasts the event list to all other modules using the notification system. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/calendar) for more information.
- Possibility to use the the calendar feed as the source for the weather (currentweather & weatherforecast) location data. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/weatherforecast) for more information.
- Added option to show rain amount in the weatherforecast default module
- Add module `updatenotification` to get an update whenever a new version is availabe. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/updatenotification) for more information.
- Add the abilty to set timezone on the date display in the Clock Module
- Add module `updatenotification` to get an update whenever a new version is available. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/updatenotification) for more information.
- Add the ability to set timezone on the date display in the Clock Module
- Ability to set date format in calendar module
- Possibility to use currentweather for the compliments
- Added option `disabled` for modules.
@@ -409,7 +470,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Added ability to define "the day after tomorrow" for calendar events (Definition for German and Dutch already included).
- Added CII Badge (we are compliant with the CII Best Practices)
- Add support for doing http basic auth when loading calendars
- Add the abilty to turn off and on the date display in the Clock Module
- Add the ability to turn off and on the date display in the Clock Module
### Fixed
- Fix typo in installer.
@@ -432,8 +493,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
- Prevent `getModules()` selectors from returning duplicate entries.
- Append endpoints of weather modules with `/` to retreive the correct data. (Issue [#337](https://github.com/MichMich/MagicMirror/issues/337))
- Corrected grammer in `module.js` from 'suspend' to 'suspended'.
- Append endpoints of weather modules with `/` to retrieve the correct data. (Issue [#337](https://github.com/MichMich/MagicMirror/issues/337))
- Corrected grammar in `module.js` from 'suspend' to 'suspended'.
- Fixed openweathermap.org URL in config sample.
- Prevent currentweather module from crashing when received data object is incorrect.
- Fix issue where translation loading prevented the UI start-up when the language was set to 'en'. (Issue [#388](https://github.com/MichMich/MagicMirror/issues/388))

View File

@@ -7,7 +7,6 @@
<a href="http://choosealicense.com/licenses/mit"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
<a href="https://travis-ci.org/MichMich/MagicMirror"><img src="https://travis-ci.org/MichMich/MagicMirror.svg" alt="Travis"></a>
<a href="https://snyk.io/test/github/MichMich/MagicMirror"><img src="https://snyk.io/test/github/MichMich/MagicMirror/badge.svg" alt="Known Vulnerabilities" data-canonical-src="https://snyk.io/test/github/MichMich/MagicMirror" style="max-width:100%;"></a>
<a href="http://slack.magicmirror.builders"><img src="http://slack.magicmirror.builders:3000/badge.svg" alt="Slack Status"></a>
</p>
**MagicMirror²** is an open source modular smart mirror platform. With a growing list of installable modules, the **MagicMirror²** allows you to convert your hallway or bathroom mirror into your personal assistant. **MagicMirror²** is built by the creator of [the original MagicMirror](http://michaelteeuw.nl/tagged/magicmirror) with the incredible help of a [growing community of contributors](https://github.com/MichMich/MagicMirror/graphs/contributors).
@@ -16,18 +15,22 @@ MagicMirror² focuses on a modular plugin system and uses [Electron](http://elec
## Table Of Contents
- [Table Of Contents](#table-of-contents)
- [Installation](#installation)
- [Raspberry Pi](#raspberry-pi)
- [General](#general)
- [Automatic Installation (Raspberry Pi only!)](#automatic-installation-raspberry-pi-only)
- [Manual Installation](#manual-installation)
- [Server Only](#server-only)
- [Client Only](#client-only)
- [Docker](#docker)
- [Configuration](#configuration)
- [Raspberry Specific](#raspberry-specific)
- [General](#general)
- [Modules](#modules)
- [Updating](#updating)
- [Known Issues](#known-issues)
- [Community](#community)
- [Contributing Guidelines](#contributing-guidelines)
- [Enjoying MagicMirror? Consider a donation!](#enjoying-magicmirror-consider-a-donation)
- [Manifesto](#manifesto)
## Installation
@@ -125,7 +128,7 @@ The following wiki links are helpful for the initial configuration of your Magic
**Note:** If you used the installer script. This step is already done for you.
2. Modify your required settings. \
Note: You'll can check your configuration running `npm run config:check` in `/home/pi/MagicMirror`.
Note: You can check your configuration running `npm run config:check` in `/home/pi/MagicMirror`.
The following properties can be configured:
@@ -199,6 +202,16 @@ Please keep the following in mind:
Thanks for your help in making MagicMirror² better!
## Enjoying MagicMirror? Consider a donation!
MagicMirror² is opensource and free. That doesn't mean we don't need any money.
Please consider a donation to help us cover the ongoing costs like webservers and email services.
If we recieve enough donations we might even be able to free up some working hours and spend some extra time improving the MagicMirror² core.
To donate, please follow [this](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=G5D8E9MR5DTD2&source=url) link.
## Manifesto
A real Manifesto is still to be written. Till then, Michael's response on [one of the repository issues](https://github.com/MichMich/MagicMirror/issues/1174) gives a great summary:

View File

@@ -47,7 +47,7 @@ sudo apt-get --assume-yes install curl wget git build-essential unzip || exit
# Check if we need to install or upgrade Node.js.
echo -e "\e[96mCheck current Node installation ...\e[0m"
NODE_INSTALL=false
if command_exists node; then
if command_exists node && command_exists npm; then
echo -e "\e[0mNode currently installed. Checking version number.";
NODE_CURRENT=$(node -v)
echo -e "\e[0mMinimum Node version: \e[1m$NODE_TESTED\e[0m"
@@ -82,7 +82,7 @@ if $NODE_INSTALL; then
# The NODE_STABLE_BRANCH variable will need to be manually adjusted when a new branch is released. (e.g. 7.x)
# Only tested (stable) versions are recommended as newer versions could break MagicMirror.
NODE_STABLE_BRANCH="9.x"
NODE_STABLE_BRANCH="10.x"
curl -sL https://deb.nodesource.com/setup_$NODE_STABLE_BRANCH | sudo -E bash -
sudo apt-get install -y nodejs
echo -e "\e[92mNode.js installation Done!\e[0m"
@@ -152,9 +152,19 @@ fi
read -p "Do you want use pm2 for auto starting of your MagicMirror (y/N)?" choice
if [[ $choice =~ ^[Yy]$ ]]; then
sudo npm install -g pm2
sudo su -c "env PATH=$PATH:/usr/bin pm2 startup linux -u pi --hp /home/pi"
pm2 start ~/MagicMirror/installers/pm2_MagicMirror.json
pm2 save
if [[ "$(ps --no-headers -o comm 1)" =~ systemd ]]; then #Checking for systemd
sudo pm2 startup systemd -u pi --hp /home/pi
else
sudo su -c "env PATH=$PATH:/usr/bin pm2 startup linux -u pi --hp /home/pi"
fi
pm2 start ~/MagicMirror/installers/pm2_MagicMirror.json
pm2 save
fi
# Disable Screensaver
read -p "Do you want to disable the screen saver? (y/N)?" choice
if [[ $choice =~ ^[Yy]$ ]]; then
sudo su -c "echo -e '@xset s noblank\n@xset s off\n@xset -dpms' >> /etc/xdg/lxsession/LXDE-pi/autostart"
export DISPLAY=:0; xset s noblank;xset s off;xset -dpms
fi
echo " "

View File

@@ -70,7 +70,7 @@ var App = function() {
if (e.code == "ENOENT") {
console.error(Utils.colors.error("WARNING! Could not find config file. Please create one. Starting with default configuration."));
} else if (e instanceof ReferenceError || e instanceof SyntaxError) {
console.error(Utils.colors.error("WARNING! Could not validate config file. Please correct syntax errors. Starting with default configuration."));
console.error(Utils.colors.error("WARNING! Could not validate config file. Starting with default configuration. Please correct syntax errors at or above this line: " + e.stack));
} else {
console.error(Utils.colors.error("WARNING! Could not load config file. Starting with default configuration. Error found: " + e));
}

View File

@@ -39,9 +39,9 @@ var MM = (function() {
dom.opacity = 0;
wrapper.appendChild(dom);
if (typeof module.data.header !== "undefined" && module.data.header !== "") {
if (typeof module.getHeader() !== "undefined" && module.getHeader() !== "") {
var moduleHeader = document.createElement("header");
moduleHeader.innerHTML = module.data.header;
moduleHeader.innerHTML = module.getHeader();
moduleHeader.className = "module-header";
dom.appendChild(moduleHeader);
}
@@ -173,6 +173,10 @@ var MM = (function() {
*/
var moduleNeedsUpdate = function(module, newHeader, newContent) {
var moduleWrapper = document.getElementById(module.identifier);
if (moduleWrapper === null) {
return false;
}
var contentWrapper = moduleWrapper.getElementsByClassName("module-content");
var headerWrapper = moduleWrapper.getElementsByClassName("module-header");

View File

@@ -212,7 +212,7 @@ var Module = Class.extend({
/* setData(data)
* Set the module data.
*
* argument data obejct - Module data.
* argument data object - Module data.
*/
setData: function (data) {
this.data = data;
@@ -226,7 +226,7 @@ var Module = Class.extend({
/* setConfig(config)
* Set the module config and combine it with the module defaults.
*
* argument config obejct - Module config.
* argument config object - Module config.
*/
setConfig: function (config) {
this.config = Object.assign({}, this.defaults, config);

View File

@@ -33,8 +33,8 @@ Therefore **we highly recommend you to include the following information in your
- A high quality screenshot of your working module
- A short, one sentence, clear description what it does (duh!)
- What external API's it depend on, including web links to those
- Wheteher the API/request require a key and the user limitations of those. (Is it free?)
- What external API's it depends upon, including web links to those
- Whether the API/request require a key and the user limitations of those. (Is it free?)
Surely this also help you get better recognition and feedback for your work.
@@ -46,8 +46,8 @@ A module can be placed in one single folder. Or multiple modules can be grouped
### Files
- **modulename/modulename.js** - This is your core module script.
- **modulename/node_helper.js** - This is an optional helper that will be loaded by the node script. The node helper and module script can communicate with each other using an intergrated socket system.
- **modulename/public** - Any files in this folder can be accesed via the browser on `/modulename/filename.ext`.
- **modulename/node_helper.js** - This is an optional helper that will be loaded by the node script. The node helper and module script can communicate with each other using an integrated socket system.
- **modulename/public** - Any files in this folder can be accessed via the browser on `/modulename/filename.ext`.
- **modulename/anyfileorfolder** Any other file or folder in the module folder can be used by the core module script. For example: *modulename/css/modulename.css* would be a good path for your additional module styles.
## The Core module file: modulename.js
@@ -89,7 +89,7 @@ After the module is initialized, the module instance has a few available module
| `this.data` | Object | The data object contain additional metadata about the module instance. (See below) |
The `this.data` data object contain the follwoing metadata:
The `this.data` data object contain the following metadata:
- `data.classes` - The classes which are added to the module dom wrapper.
- `data.file` - The filename of the core module file.
- `data.path` - The path of the module folder.
@@ -98,7 +98,7 @@ The `this.data` data object contain the follwoing metadata:
#### `defaults: {}`
Any properties defined in the defaults object, will be merged with the module config as defined in the user's config.js file. This is the best place to set your modules's configuration defaults. Any of the module configuration properties can be accessed using `this.config.propertyName`, but more about that later.
Any properties defined in the defaults object, will be merged with the module config as defined in the user's config.js file. This is the best place to set your modules' configuration defaults. Any of the module configuration properties can be accessed using `this.config.propertyName`, but more about that later.
#### `requiresVersion:`
@@ -134,7 +134,7 @@ loaded: function(callback) {
````
#### `start()`
This method is called when all modules are loaded an the system is ready to boot up. Keep in mind that the dom object for the module is not yet created. The start method is a perfect place to define any additional module properties:
This method is called when all modules are loaded and the system is ready to boot up. Keep in mind that the dom object for the module is not yet created. The start method is a perfect place to define any additional module properties:
**Example:**
````javascript
@@ -161,7 +161,7 @@ getScripts: function() {
}
````
**Note:** If a file can not be loaded, the boot up of the mirror will stall. Therefore it's advised not to use any external urls.
**Note:** If a file can not be loaded, the boot up of the mirror will stall. Therefore, it's advised not to use any external urls.
#### `getStyles()`
@@ -174,14 +174,14 @@ The getStyles method is called to request any additional stylesheets that need t
getStyles: function() {
return [
'script.css', // will try to load it from the vendor folder, otherwise it will load is from the module folder.
'font-awesome.css', // this file is available in the vendor folder, so it doesn't need to be avialable in the module folder.
'font-awesome.css', // this file is available in the vendor folder, so it doesn't need to be available in the module folder.
this.file('anotherfile.css'), // this file will be loaded straight from the module folder.
'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css', // this file will be loaded from the bootstrapcdn servers.
]
}
````
**Note:** If a file can not be loaded, the boot up of the mirror will stall. Therefore it's advised not to use any external urls.
**Note:** If a file can not be loaded, the boot up of the mirror will stall. Therefore, it's advised not to use any external URLs.
#### `getTranslations()`
**Should return: Dictionary**
@@ -239,7 +239,7 @@ That MagicMirror core has the ability to send notifications to modules. Or even
- `notification` - String - The notification identifier.
- `payload` - AnyType - The payload of a notification.
- `sender` - Module - The sender of the notification. If this argument is `undefined`, the sender of the notififiction is the core system.
- `sender` - Module - The sender of the notification. If this argument is `undefined`, the sender of the notification is the core system.
**Example:**
````javascript
@@ -346,7 +346,7 @@ Possible configurable options:
- `lockString` - String - When setting lock string, the module can not be shown without passing the correct lockstring. This way (multiple) modules can prevent a module from showing. It's considered best practice to use your modules identifier as the locksString: `this.identifier`. See *visibility locking* below.
**Note 1:** If the hide animation is canceled, for instance because the show method is called before the hide animation was finished, the callback will not be called.<br>
**Note 1:** If the hide animation is cancelled, for instance because the show method is called before the hide animation was finished, the callback will not be called.<br>
**Note 2:** If the hide animation is hijacked (an other method calls hide on the same module), the callback will not be called.<br>
**Note 3:** If the dom is not yet created, the hide method won't work. Wait for the `DOM_OBJECTS_CREATED` [notification](#notificationreceivednotification-payload-sender).
@@ -371,7 +371,7 @@ Possible configurable options:
(*Introduced in version: 2.1.0.*)
Visiblity locking helps the module system to prevent unwanted hide/show actions. The following scenario explains the concept:
Visibility locking helps the module system to prevent unwanted hide/show actions. The following scenario explains the concept:
**Module B asks module A to hide:**
````javascript
@@ -436,7 +436,7 @@ If no translation is found, a fallback will be used. The fallback sequence is as
- 4. Translation as defined in core translation file of the fallback language (the first defined core translation file).
- 5. The key (identifier) of the translation.
When adding translations to your module, it's a good idea to see if an apropriate translation is already available in the [core translation files](https://github.com/MichMich/MagicMirror/tree/master/translations). This way, your module can benefit from the existing translations.
When adding translations to your module, it's a good idea to see if an appropriate translation is already available in the [core translation files](https://github.com/MichMich/MagicMirror/tree/master/translations). This way, your module can benefit from the existing translations.
**Example:**
````javascript
@@ -490,7 +490,7 @@ this.translate("RUNNING", {
)}); // Will return a translated string for the identifier RUNNING, replacing `{timeUntilEnd}` with the contents of the variable `timeUntilEnd` in the order that translator intended. (has a fallback)
````
**Example swedish .json file that does not have the variable in it:**
**Example Swedish .json file that does not have the variable in it:**
````javascript
{
"RUNNING": "Slutar",

View File

@@ -43,10 +43,11 @@ self.sendNotification("SHOW_ALERT", {});
```
### Notification params
| Option | Description
| --------- | -----------
| `title` | The title of the notification. <br><br> **Possible values:** `text` or `html`
| `message` | The message of the notification. <br><br> **Possible values:** `text` or `html`
| Option | Description
| ------------------ | -----------
| `title` | The title of the notification. <br><br> **Possible values:** `text` or `html`
| `message` | The message of the notification. <br><br> **Possible values:** `text` or `html`
| `timer` (optional) | How long the notification should stay visible in ms. <br> If absent, the default `display_time` is used. <br> **Possible values:** `int` `float`
### Alert params
@@ -61,4 +62,4 @@ self.sendNotification("SHOW_ALERT", {});
## Open Source Licenses
### [NotificationStyles](https://github.com/codrops/NotificationStyles)
See [ympanus.net](http://tympanus.net/codrops/licensing/) for license.
See [tympanus.net](http://tympanus.net/codrops/licensing/) for license.

View File

@@ -24,7 +24,7 @@ Module.register("alert",{
return ["classie.js", "modernizr.custom.js", "notificationFx.js"];
},
getStyles: function() {
return ["ns-default.css"];
return ["ns-default.css", "font-awesome.css"];
},
// Define required translations.
getTranslations: function() {
@@ -51,7 +51,7 @@ Module.register("alert",{
message: msg,
layout: "growl",
effect: this.config.effect,
ttl: this.config.display_time
ttl: message.timer !== undefined ? message.timer : this.config.display_time
}).show();
},
show_alert: function(params, sender) {

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
/* Based on work by http://tympanus.net/codrops/licensing/ */
.ns-box {
background: #fff;
background-color: rgba(0, 0, 0, 0.93);
padding: 17px;
line-height: 1.4;
margin-bottom: 10px;
@@ -12,7 +12,10 @@
display: table;
word-wrap: break-word;
max-width: 100%;
border-width: 1px;
border-radius: 5px;
border-style: solid;
border-color: #666;
}
.ns-alert {

View File

@@ -32,6 +32,7 @@ The following properties can be configured:
| `defaultSymbol` | The default symbol. <br><br> **Possible values:** See [Font Awsome](http://fontawesome.io/icons/) website. <br> **Default value:** `calendar`
| `maxTitleLength` | The maximum title length. <br><br> **Possible values:** `10` - `50` <br> **Default value:** `25`
| `wrapEvents` | Wrap event titles to multiple lines. Breaks lines at the length defined by `maxTitleLength`. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `maxTitleLines` | The maximum number of lines a title will wrap vertically before being cut (Only enabled if `wrapEvents` is also enabled). <br><br> **Possible values:** `0` - `10` <br> **Default value:** `3`
| `fetchInterval` | How often does the content needs to be fetched? (Milliseconds) <br><br> **Possible values:** `1000` - `86400000` <br> **Default value:** `300000` (5 minutes)
| `animationSpeed` | Speed of the update animation. (Milliseconds) <br><br> **Possible values:** `0` - `5000` <br> **Default value:** `2000` (2 seconds)
| `fade` | Fade the future events to black. (Gradient) <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
@@ -52,6 +53,8 @@ The following properties can be configured:
| `hidePrivate` | Hides private calendar events. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `hideOngoing` | Hides calendar events that have already started. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `excludedEvents` | An array of words / phrases from event titles that will be excluded from being shown. <br><br>Additionally advanced filter objects can be passed in. Below is the configuration for the advance filtering object.<br>**Required**<br>`filterBy` - string used to determine if filter is applied.<br>**Optional**<br>`until` - Time before an event to display it Ex: [`'3 days'`, `'2 months'`, `'1 week'`]<br>`caseSensitive` - By default, excludedEvents are case insensitive, set this to true to enforce case sensitivity<br>`regex` - set to `true` if filterBy is a regex. For those not familiar with regex it is used for pattern matching, please see [here](https://regexr.com/) for more info.<br><br> **Example:** `['Birthday', 'Hide This Event', {filterBy: 'Payment', until: '6 days', caseSensitive: true}, {filterBy: '^[0-9]{1,}.*', regex: true}]` <br> **Default value:** `[]`
| `sliceMultiDayEvents` | If this is set to true, events exceeding at least one midnight will be sliced into separate events including a counter like (1/2). This is especially helpful in "dateheaders" mode. Events will be sliced at midnight, end time for all events but the last will be 23:59 **Default value:** `true`
### Calendar configuration
@@ -87,6 +90,7 @@ config: {
| `repeatingCountTitle` | The count title for yearly repating events in this calendar. <br><br> **Example:** `'Birthday'`
| `maximumEntries` | The maximum number of events shown. Overrides global setting. **Possible values:** `0` - `100`
| `maximumNumberOfDays` | The maximum number of days in the future. Overrides global setting
| `name` | The name of the calendar. Included in event broadcasts as `calendarName`.
| `auth` | The object containing options for authentication against the calendar.
| `symbolClass` | Add a class to the cell of symbol.
| `titleClass` | Add a class to the title's cell.

View File

@@ -19,13 +19,14 @@ Module.register("calendar", {
defaultRepeatingCountTitle: "",
maxTitleLength: 25,
wrapEvents: false, // wrap events to multiple lines breaking at maxTitleLength
maxTitleLines: 3,
fetchInterval: 5 * 60 * 1000, // Update every 5 minutes.
animationSpeed: 2000,
fade: true,
urgency: 7,
timeFormat: "relative",
dateFormat: "MMM Do",
dateEndFormat: "HH:mm",
dateEndFormat: "LT",
fullDayEventDateFormat: "MMM Do",
showEnd: false,
getRelative: 6,
@@ -46,12 +47,13 @@ Module.register("calendar", {
"'s birthday": ""
},
broadcastEvents: true,
excludedEvents: []
excludedEvents: [],
sliceMultiDayEvents: false
},
// Define required scripts.
getStyles: function () {
return ["calendar.css", "font-awesome5.css", "font-awesome5.v4shims.css"];
return ["calendar.css", "font-awesome.css"];
},
// Define required scripts.
@@ -103,6 +105,13 @@ Module.register("calendar", {
}
this.addCalendar(calendar.url, calendar.auth, calendarConfig);
// Trigger ADD_CALENDAR every fetchInterval to make sure there is always a calendar
// fetcher running on the server side.
var self = this;
setInterval(function() {
self.addCalendar(calendar.url, calendar.auth, calendarConfig);
}, self.config.fetchInterval);
}
this.calendarData = {};
@@ -220,7 +229,7 @@ Module.register("calendar", {
var titleWrapper = document.createElement("td"),
repeatingCountTitle = "";
if (this.config.displayRepeatingCountTitle) {
if (this.config.displayRepeatingCountTitle && event.firstYear !== undefined) {
repeatingCountTitle = this.countTitleForUrl(event.url);
@@ -296,12 +305,12 @@ Module.register("calendar", {
if (this.config.timeFormat === "absolute") {
if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * oneDay))) {
// This event falls within the config.urgency period that the user has set
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").from(moment().format("YYYYMMDD")));
} else {
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format(this.config.fullDayEventDateFormat));
}
} else {
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").from(moment().format("YYYYMMDD")));
}
}
if(this.config.showEnd){
@@ -447,7 +456,31 @@ Module.register("calendar", {
}
event.url = c;
event.today = event.startDate >= today && event.startDate < (today + 24 * 60 * 60 * 1000);
events.push(event);
/* if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days,
* otherwise, esp. in dateheaders mode it is not clear how long these events are.
*/
if (this.config.sliceMultiDayEvents) {
var midnight = moment(event.startDate, "x").clone().startOf("day").add(1, "day").format("x"); //next midnight
var count = 1;
var maxCount = Math.ceil(((event.endDate - 1) - moment(event.startDate, "x").endOf("day").format("x"))/(1000*60*60*24)) + 1
if (event.endDate > midnight) {
while (event.endDate > midnight) {
var nextEvent = JSON.parse(JSON.stringify(event)); //make a copy without reference to the original event
nextEvent.startDate = midnight;
event.endDate = midnight;
event.title += " (" + count + "/" + maxCount + ")";
events.push(event);
event = nextEvent;
count += 1;
midnight = moment(midnight, "x").add(1, "day").format("x"); //move further one day for next split
}
event.title += " ("+count+"/"+maxCount+")";
}
events.push(event);
} else {
events.push(event);
}
}
}
@@ -536,6 +569,17 @@ Module.register("calendar", {
return this.getCalendarProperty(url, "timeClass", "");
},
/* calendarNameForUrl(url)
* Retrieves the calendar name for a specific url.
*
* argument url string - Url to look for.
*
* return string - The name of the calendar
*/
calendarNameForUrl: function (url) {
return this.getCalendarProperty(url, "name", "");
},
/* colorForUrl(url)
* Retrieves the color for a specific url.
*
@@ -584,9 +628,10 @@ Module.register("calendar", {
* @param {string} string Text string to shorten
* @param {number} maxLength The max length of the string
* @param {boolean} wrapEvents Wrap the text after the line has reached maxLength
* @param {number} maxTitleLines The max number of vertical lines before cutting event title
* @returns {string} The shortened string
*/
shorten: function (string, maxLength, wrapEvents) {
shorten: function (string, maxLength, wrapEvents, maxTitleLines) {
if (typeof string !== "string") {
return "";
}
@@ -595,12 +640,21 @@ Module.register("calendar", {
var temp = "";
var currentLine = "";
var words = string.split(" ");
var line = 0;
for (var i = 0; i < words.length; i++) {
var word = words[i];
if (currentLine.length + word.length < (typeof maxLength === "number" ? maxLength : 25) - 1) { // max - 1 to account for a space
currentLine += (word + " ");
} else {
line++;
if (line > maxTitleLines - 1) {
if (i < words.length) {
currentLine += "&hellip;";
}
break;
}
if (currentLine.length > 0) {
temp += (currentLine + "<br>" + word + " ");
} else {
@@ -651,7 +705,7 @@ Module.register("calendar", {
title = title.replace(needle, replacement);
}
title = this.shorten(title, this.config.maxTitleLength, this.config.wrapEvents);
title = this.shorten(title, this.config.maxTitleLength, this.config.wrapEvents, this.config.maxTitleLines);
return title;
},
@@ -666,6 +720,7 @@ Module.register("calendar", {
for (var e in calendar) {
var event = cloneObject(calendar[e]);
event.symbol = this.symbolsForUrl(url);
event.calendarName = this.calendarNameForUrl(url);
event.color = this.colorForUrl(url);
delete event.url;
eventList.push(event);

View File

@@ -273,7 +273,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
/* isFullDayEvent(event)
* Checks if an event is a fullday event.
*
* argument event obejct - The event object to check.
* argument event object - The event object to check.
*
* return bool - The event is a fullday event.
*/

View File

@@ -80,16 +80,45 @@
}
}
var addTZ = function(dt, name, params){
var addTZ = function(dt, params){
var p = parseParams(params);
if (params && p){
dt[name].tz = p.TZID
if (params && p && dt){
dt.tz = p.TZID
}
return dt
}
var parseTimestamp = function(val){
//typical RFC date-time format
var comps = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(Z)?$/.exec(val);
if (comps !== null) {
if (comps[7] == 'Z'){ // GMT
return new Date(Date.UTC(
parseInt(comps[1], 10),
parseInt(comps[2], 10)-1,
parseInt(comps[3], 10),
parseInt(comps[4], 10),
parseInt(comps[5], 10),
parseInt(comps[6], 10 )
));
// TODO add tz
} else {
return new Date(
parseInt(comps[1], 10),
parseInt(comps[2], 10)-1,
parseInt(comps[3], 10),
parseInt(comps[4], 10),
parseInt(comps[5], 10),
parseInt(comps[6], 10)
);
}
}
return undefined;
}
var dateParam = function(name){
return function(val, params, curr){
@@ -108,37 +137,24 @@
comps[3]
);
return addTZ(curr, name, params);
curr[name] = addTZ(curr[name], params);
return curr;
}
}
curr[name] = []
val.split(',').forEach(function(val){
var newDate = parseTimestamp(val);
curr[name].push(addTZ(newDate, params));
});
//typical RFC date-time format
var comps = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(Z)?$/.exec(val);
if (comps !== null) {
if (comps[7] == 'Z'){ // GMT
curr[name] = new Date(Date.UTC(
parseInt(comps[1], 10),
parseInt(comps[2], 10)-1,
parseInt(comps[3], 10),
parseInt(comps[4], 10),
parseInt(comps[5], 10),
parseInt(comps[6], 10 )
));
// TODO add tz
} else {
curr[name] = new Date(
parseInt(comps[1], 10),
parseInt(comps[2], 10)-1,
parseInt(comps[3], 10),
parseInt(comps[4], 10),
parseInt(comps[5], 10),
parseInt(comps[6], 10)
);
}
if (curr[name].length === 0){
delete curr[name];
} else if (curr[name].length === 1){
curr[name] = curr[name][0];
}
return addTZ(curr, name, params)
return curr;
}
}
@@ -148,7 +164,11 @@
if (date.exdates === undefined) {
date.exdates = [];
}
date.exdates.push(date.exdate);
if (Array.isArray(date.exdate)){
date.exdates = date.exdates.concat(date.exdate);
} else {
date.exdates.push(date.exdate);
}
return date;
}
}

View File

@@ -137,7 +137,8 @@ Module.register("clock",{
clockCircle.style.backgroundSize = "100%";
// The following line solves issue: https://github.com/MichMich/MagicMirror/issues/611
clockCircle.style.border = "1px solid black";
// clockCircle.style.border = "1px solid black";
clockCircle.style.border = "rgba(0, 0, 0, 0.1)"; //Updated fix for Issue 611 where non-black backgrounds are used
} else if (this.config.analogFace != "none") {
clockCircle.style.border = "2px solid white";

View File

@@ -50,7 +50,7 @@ The following properties can be configured:
| `showIndoorTemperature` | If you have another module that emits the INDOOR_TEMPERATURE notification, the indoor temperature will be displayed <br> **Default value:** `false`
| `onlyTemp` | Show only current Temperature and weather icon without windspeed, sunset, sunrise time and feels like. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `showFeelsLike` | Shows the Feels like temperature weather. <br><br> **Possible values:**`true` or `false`<br>**Default value:** `true`
| `useKMPHWind` | Uses KMPH as units for windspeed. <br><br> **Possible values:**`true` or `false`<br>**Default value:** `false`
| `useKMPHwind` | Uses KMPH as units for windspeed. <br><br> **Possible values:**`true` or `false`<br>**Default value:** `false`
| `useBeaufort` | Pick between using the Beaufort scale for wind speed or using the default units. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `lang` | The language of the days. <br><br> **Possible values:** `en`, `nl`, `ru`, etc ... <br> **Default value:** uses value of _config.language_
| `decimalSymbol` | The decimal symbol to use.<br><br> **Possible values:** `.`, `,` or any other symbol.<br> **Default value:** `.`

View File

@@ -71,7 +71,7 @@ Module.register("currentweather",{
firstEvent: false,
// create a variable to hold the location name based on the API result.
fetchedLocatioName: "",
fetchedLocationName: "",
// Define required scripts.
getScripts: function() {
@@ -198,16 +198,19 @@ Module.register("currentweather",{
large.appendChild(weatherIcon);
var degreeLabel = "";
if (this.config.degreeLabel) {
switch (this.config.units ) {
if (this.config.units === "metric" || this.config.units === "imperial") {
degreeLabel += "°";
}
if(this.config.degreeLabel) {
switch(this.config.units) {
case "metric":
degreeLabel = "C";
degreeLabel += "C";
break;
case "imperial":
degreeLabel = "F";
degreeLabel += "F";
break;
case "default":
degreeLabel = "K";
degreeLabel += "K";
break;
}
}
@@ -218,7 +221,7 @@ Module.register("currentweather",{
var temperature = document.createElement("span");
temperature.className = "bright";
temperature.innerHTML = " " + this.temperature.replace(".", this.config.decimalSymbol) + "&deg;" + degreeLabel;
temperature.innerHTML = " " + this.temperature.replace(".", this.config.decimalSymbol) + degreeLabel;
large.appendChild(temperature);
if (this.config.showIndoorTemperature && this.indoorTemperature) {
@@ -228,7 +231,7 @@ Module.register("currentweather",{
var indoorTemperatureElem = document.createElement("span");
indoorTemperatureElem.className = "bright";
indoorTemperatureElem.innerHTML = " " + this.indoorTemperature.replace(".", this.config.decimalSymbol) + "&deg;" + degreeLabel;
indoorTemperatureElem.innerHTML = " " + this.indoorTemperature.replace(".", this.config.decimalSymbol) + degreeLabel;
large.appendChild(indoorTemperatureElem);
}
@@ -251,7 +254,7 @@ Module.register("currentweather",{
var feelsLike = document.createElement("span");
feelsLike.className = "dimmed";
feelsLike.innerHTML = this.translate("FEELS") + " " + this.feelsLike + "&deg;" + degreeLabel;
feelsLike.innerHTML = this.translate("FEELS") + " " + this.feelsLike + degreeLabel;
small.appendChild(feelsLike);
wrapper.appendChild(small);
@@ -262,8 +265,8 @@ Module.register("currentweather",{
// Override getHeader method.
getHeader: function() {
if (this.config.appendLocationNameToHeader) {
return this.data.header + " " + this.fetchedLocatioName;
if (this.config.appendLocationNameToHeader && this.data.header !== undefined) {
return this.data.header + " " + this.fetchedLocationName;
}
return this.data.header;

View File

@@ -46,6 +46,7 @@ MagicMirror's [notification mechanism](https://github.com/MichMich/MagicMirror/t
| `ARTICLE_MORE_DETAILS` | When received the _first time_, shows the corresponding description of the currently displayed news title. <br> The module expects that the module's configuration option `showDescription` is set to `false` (default value). <br><br> When received a _second consecutive time_, shows the full news article in an IFRAME. <br> This requires that the news page can be embedded in an IFRAME, e.g. doesn't have the HTTP response header [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) set to e.g. `DENY`.<br><br>When received the _next consecutive times_, reloads the page and scrolls down by `scrollLength` pixels to paginate through the article.
| `ARTICLE_LESS_DETAILS` | Hides the summary or full news article and only displays the news title of the currently viewed news item.
| `ARTICLE_TOGGLE_FULL` | Toogles article in fullscreen.
| `ARTICLE_INFO_REQUEST` | Causes `newsfeed` to respond with the notification `ARTICLE_INFO_RESPONSE`, the payload of which provides the `title`, `source`, `date`, `desc` and `url` of the current news title.
Note the payload of the sent notification event is ignored.

View File

@@ -189,7 +189,7 @@ Module.register("newsfeed",{
fullArticle.style.top = "0";
fullArticle.style.left = "0";
fullArticle.style.border = "none";
fullArticle.src = typeof this.newsItems[this.activeItem].url === "string" ? this.newsItems[this.activeItem].url : this.newsItems[this.activeItem].url.href;
fullArticle.src = this.getActiveItemURL()
fullArticle.style.zIndex = 1;
wrapper.appendChild(fullArticle);
}
@@ -210,6 +210,10 @@ Module.register("newsfeed",{
return wrapper;
},
getActiveItemURL: function() {
return typeof this.newsItems[this.activeItem].url === "string" ? this.newsItems[this.activeItem].url : this.newsItems[this.activeItem].url.href;
},
/* registerFeeds()
* registers the feeds to be used by the backend.
*/
@@ -387,6 +391,14 @@ Module.register("newsfeed",{
} else {
this.showFullArticle();
}
} else if (notification === "ARTICLE_INFO_REQUEST"){
this.sendNotification("ARTICLE_INFO_RESPONSE", {
title: this.newsItems[this.activeItem].title,
source: this.newsItems[this.activeItem].sourceTitle,
date: this.newsItems[this.activeItem].pubdate,
desc: this.newsItems[this.activeItem].description,
url: this.getActiveItemURL()
})
} else {
Log.info(this.name + " - unknown notification, ignoring: " + notification);
}

View File

@@ -65,8 +65,10 @@ module.exports = NodeHelper.create({
data.module = sg.module;
if (!err) {
sg.git.log({"-1": null}, function(err, data2) {
data.hash = data2.latest.hash;
self.sendSocketNotification("STATUS", data);
if (!err && data2.latest && "hash" in data2.latest) {
data.hash = data2.latest.hash;
self.sendSocketNotification("STATUS", data);
}
});
}
});

View File

@@ -2,7 +2,7 @@
This module is aimed to be the replacement for the current `currentweather` and `weatherforcast` modules. The module will be configurable to be used as a current weather view, or to show the forecast. This way the module can be used twice to fullfil both purposes.
The biggest cange is the use of weather providers. This way we are not bound to one API source. And users can choose which API they want to use as their source.
The biggest change is the use of weather providers. This way we are not bound to one API source. And users can choose which API they want to use as their source.
The module is in a very early stage, and needs a lot of work. It's API isn't set in stone, so keep that in mind when you want to contribute.
@@ -35,21 +35,21 @@ The following properties can be configured:
| Option | Description
| ---------------------------- | -----------
| `weatherProvider` | Which weather provider should be used. <br><br> **Possible values:** `openweathermap` and `darksky` <br> **Default value:** `openweathermap`
| `type` | Which type of weather data should be displayed. <br><br> **Possible values:** `current` and `forecast` <br> **Default value:** `current`
| `units` | What units to use. Specified by config.js <br><br> **Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` =Fahrenheit <br> **Default value:** `config.units`
| `weatherProvider` | Which weather provider should be used. <br><br> **Possible values:** `openweathermap` , `darksky` , or `weathergov` <br> **Default value:** `openweathermap`
| `type` | Which type of weather data should be displayed. <br><br> **Possible values:** `current` or `forecast` <br> **Default value:** `current`
| `units` | What units to use. Specified by config.js <br><br> **Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` = Fahrenheit <br> **Default value:** `config.units`
| `roundTemp` | Round temperature value to nearest integer. <br><br> **Possible values:** `true` (round to integer) or `false` (display exact value with decimal point) <br> **Default value:** `false`
| `degreeLabel` | Show the degree label for your chosen units (Metric = C, Imperial = F, Kelvins = K). <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `degreeLabel` | Show the degree label for your chosen units (Metric = C, Imperial = F, Kelvin = K). <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `updateInterval` | How often does the content needs to be fetched? (Milliseconds) <br><br> **Possible values:** `1000` - `86400000` <br> **Default value:** `600000` (10 minutes)
| `animationSpeed` | Speed of the update animation. (Milliseconds) <br><br> **Possible values:**`0` - `5000` <br> **Default value:** `1000` (1 second)
| `animationSpeed` | Speed of the update animation. (Milliseconds) <br><br> **Possible values:** `0` - `5000` <br> **Default value:** `1000` (1 second)
| `timeFormat` | Use 12 or 24 hour format. <br><br> **Possible values:** `12` or `24` <br> **Default value:** uses value of _config.timeFormat_
| `showPeriod` | Show the period (am/pm) with 12 hour format <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `showPeriodUpper` | Show the period (AM/PM) with 12 hour format as uppercase <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `lang` | The language of the days. <br><br> **Possible values:** `en`, `nl`, `ru`, etc ... <br> **Default value:** uses value of _config.language_
| `decimalSymbol` | The decimal symbol to use.<br><br> **Possible values:** `.`, `,` or any other symbol.<br> **Default value:** `.`
| `initialLoadDelay` | The initial delay before loading. If you have multiple modules that use the same API key, you might want to delay one of the requests. (Milliseconds) <br><br> **Possible values:** `1000` - `5000` <br> **Default value:** `0`
| `appendLocationNameToHeader` | If set to `true`, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly intresting when using calender based weather. <br><br> **Default value:** `true`
| `calendarClass` | The class for the calender module to base the event based weather information on. <br><br> **Default value:** `'calendar'`
| `initialLoadDelay` | The initial delay before loading. If you have multiple modules that use the same API key, you might want to delay one of the requests. (Milliseconds) <br><br> **Possible values:** `1000` - `5000` <br> **Default value:** `0`
| `appendLocationNameToHeader` | If set to `true`, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly interesting when using calender based weather. <br><br> **Default value:** `true`
| `calendarClass` | The class for the calender module to base the event based weather information on. <br><br> **Default value:** `'calendar'`
#### Current weather options
@@ -62,36 +62,48 @@ The following properties can be configured:
| `showHumidity` | Show the current humidity <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `showIndoorTemperature` | If you have another module that emits the `INDOOR_TEMPERATURE` notification, the indoor temperature will be displayed <br> **Default value:** `false`
| `showIndoorHumidity` | If you have another module that emits the `INDOOR_HUMIDITY` notification, the indoor humidity will be displayed <br> **Default value:** `false`
| `showFeelsLike` | Shows the Feels like temperature weather. <br><br> **Possible values:**`true` or `false`<br>**Default value:** `true`
| `showFeelsLike` | Shows the Feels like temperature weather. <br><br> **Possible values:** `true` or `false`<br>**Default value:** `true`
#### Weather forecast options
| Option | Description
| ---------------------------- | -----------
| `tableClass` | The class for the forecast table. <br><br> **Default value:** `'small'`
| `colored` | If set to `true`, the min and max temperature are color coded. <br><br> **Default value:** `false`
| `showRainAmount` | Show the amount of rain in the forecast <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `tableClass` | The class for the forecast table. <br><br> **Default value:** `'small'`
| `colored` | If set to `true`, the min and max temperature are color coded. <br><br> **Default value:** `false`
| `showPrecipitationAmount` | Show the amount of rain/snow in the forecast <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `fade` | Fade the future events to black. (Gradient) <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `fadePoint` | Where to start fade? <br><br> **Possible values:** `0` (top of the list) - `1` (bottom of list) <br> **Default value:** `0.25`
| `maxNumberOfDays` | How many days of forecast to return. Specified by config.js <br><br> **Possible values:** `1` - `16` <br> **Default value:** `5` (5 days) <br> This value is optional. By default the weatherforecast module will return 5 days.
### Openweathermap options
| Option | Description
| ---------------------------- | -----------
| `apiVersion` | The OpenWeatherMap API version to use. <br><br> **Default value:** `2.5`
| `apiBase` | The OpenWeatherMap base URL. <br><br> **Default value:** `'http://api.openweathermap.org/data/'`
| `weatherEndpoint` | The OpenWeatherMap API endPoint. <br><br> **Possible values:** `/weather` or `/forecast/daily` <br> **Default value:** `'/weather'`
| `apiVersion` | The OpenWeatherMap API version to use. <br><br> **Default value:** `2.5`
| `apiBase` | The OpenWeatherMap base URL. <br><br> **Default value:** `'http://api.openweathermap.org/data/'`
| `weatherEndpoint` | The OpenWeatherMap API endPoint. <br><br> **Possible values:** `/weather`, `/forecast` (free users) or `/forecast/daily` (paying users or old apiKey only) <br> **Default value:** `'/weather'`
| `locationID` | Location ID from [OpenWeatherMap](https://openweathermap.org/find) **This will override anything you put in location.** <br> Leave blank if you want to use location. <br> **Example:** `1234567` <br> **Default value:** `false` <br><br> **Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used.
| `location` | The location used for weather information. <br><br> **Example:** `'Amsterdam,Netherlands'` <br> **Default value:** `false` <br><br> **Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used.
| `apiKey` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account. <br><br> This value is **REQUIRED**
| `apiKey` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account. <br><br> This value is **REQUIRED**
### Darksky options
| Option | Description
| ---------------------------- | -----------
| `apiBase` | The DarkSky base URL. The darksky api has disabled [cors](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), therefore a proxy is required. <br><br> **Possible value:** `'https://cors-anywhere.herokuapp.com/https://api.darksky.net'` <br> This value is **REQUIRED**
| `weatherEndpoint` | The DarkSky API endPoint. <br><br> **Possible values:** `/forecast` <br> This value is **REQUIRED**
| `apiKey` | The [DarkSky](https://darksky.net/dev/register) API key, which can be obtained by creating an DarkSky account. <br><br> This value is **REQUIRED**
| `lat` | The geo coordinate latitude. <br><br> This value is **REQUIRED**
| `lon` | The geo coordinate longitude. <br><br> This value is **REQUIRED**
| `apiBase` | The DarkSky base URL. The darksky api has disabled [cors](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), therefore a proxy is required. <br><br> **Possible value:** `'https://cors-anywhere.herokuapp.com/https://api.darksky.net'` <br> This value is **REQUIRED**
| `weatherEndpoint` | The DarkSky API endPoint. <br><br> **Possible values:** `/forecast` <br> This value is **REQUIRED**
| `apiKey` | The [DarkSky](https://darksky.net/dev/register) API key, which can be obtained by creating an DarkSky account. <br><br> This value is **REQUIRED**
| `lat` | The geo coordinate latitude. <br><br> This value is **REQUIRED**
| `lon` | The geo coordinate longitude. <br><br> This value is **REQUIRED**
### Weather.gov options
| Option | Description
| ---------------------------- | -----------
| `apiBase` | The weather.gov base URL. <br><br> **Possible value:** `'https://api.weather.gov/points/'` <br> This value is **REQUIRED**
| `weatherEndpoint` | The weather.gov API endPoint. <br><br> **Possible values:** `/forecast` for forecast and `/forecast/hourly` for current. <br> This value is **REQUIRED**
| `lat` | The geo coordinate latitude. <br><br> This value is **REQUIRED**
| `lon` | The geo coordinate longitude. <br><br> This value is **REQUIRED**
## API Provider Development

View File

@@ -4,31 +4,30 @@
<span class="wi wi-strong-wind dimmed"></span>
<span>
{% if config.useBeaufort %}
{{current.beaufortWindSpeed() | round}}
{{ current.beaufortWindSpeed() | round }}
{% else %}
{{current.windSpeed | round}}
{{ current.windSpeed | round }}
{% endif %}
{% if config.showWindDirection %}
<sup>
{% if config.showWindDirectionAsArrow %}
<i class="fa fa-long-arrow-up" style="transform:rotate({{current.windDirection}}deg);"></i>
<i class="fa fa-long-arrow-up" style="transform:rotate({{ current.windDirection }}deg);"></i>
{% else %}
{{current.cardinalWindDirection() | translate}}
{{ current.cardinalWindDirection() | translate }}
{% endif %}
&nbsp;
</sup>
{% endif %}
</span>
{% if config.showHumidity and current.humidity %}
<span>{{ current.humidity }}</span><sup>&nbsp;<i class="wi wi-humidity humidityIcon"></i></sup>
<span>{{ current.humidity | decimalSymbol }}</span><sup>&nbsp;<i class="wi wi-humidity humidityIcon"></i></sup>
{% endif %}
<span class="wi dimmed wi-{{current.nextSunAction()}}"></span>
<span class="wi dimmed wi-{{ current.nextSunAction() }}"></span>
<span>
{% if current.nextSunAction() == "sunset" %}
{{current.sunset | formatTime}}
{{ current.sunset | formatTime }}
{% else %}
{{current.sunrise | formatTime}}
{{ current.sunrise | formatTime }}
{% endif %}
</span>
</div>
@@ -36,33 +35,39 @@
<div class="large light">
<span class="wi weathericon wi-{{current.weatherType}}"></span>
<span class="bright">
{{current.temperature | roundValue | unit("temperature")}}
{{ current.temperature | roundValue | unit("temperature") | decimalSymbol }}
</span>
</div>
<div class="normal light indoor">
{% if config.showIndoorTemperature and indoor.temperature %}
<span class="fa fa-home"></span>
<span class="bright">
{{indoor.temperature | roundValue | unit("temperature")}}
</span>
<div>
<span class="fa fa-home"></span>
<span class="bright">
{{ indoor.temperature | roundValue | unit("temperature") | decimalSymbol }}
</span>
</div>
{% endif %}
{% if config.showIndoorHumidity and indoor.humidity %}
<span class="fa fa-tint"></span>
<span class="bright">
{{indoor.humidity | roundValue}}%
</span>
<div>
<span class="fa fa-tint"></span>
<span class="bright">
{{ indoor.humidity | roundValue | unit("humidity") | decimalSymbol }}
</span>
</div>
{% endif %}
</div>
{% if config.showFeelsLike and not config.onlyTemp %}
<div class="normal medium">
<span class="dimmed">
{{ "FEELS" | translate }} {{ current.feelsLike() | roundValue | unit("temperature") }}
{{ "FEELS" | translate }} {{ current.feelsLike() | roundValue | unit("temperature") | decimalSymbol }}
</span>
</div>
{% endif %}
{% else %}
<div class="dimmed light small">
{{"LOADING" | translate}}
{{ "LOADING" | translate | safe }}
</div>
{% endif %}
<!-- Unclomment the line below to see the contents of the `current` object. -->
<!-- Uncomment the line below to see the contents of the `current` object. -->
<!-- <div style="word-wrap:break-word" class="xsmall dimmed">{{current | dump}}</div> -->

View File

@@ -1,26 +1,32 @@
{% if forecast %}
<table class="{{config.tableClass}}">
{% set numSteps = forecast | calcNumSteps %}
{% set currentStep = 0 %}
<table class="{{ config.tableClass }}">
{% set forecast = forecast.slice(0, numSteps) %}
{% for f in forecast %}
<tr {% if config.colored %}class="colored"{% endif %}>
<td class="day">{{f.date.format('ddd')}}</td>
<td class="bright weather-icon"><span class="wi weathericon wi-{{f.weatherType}}"></span></td>
<tr {% if config.colored %}class="colored"{% endif %} {% if config.fade %}style="opacity: {{ currentStep | opacity(numSteps) }};"{% endif %}>
<td class="day">{{ f.date.format('ddd') }}</td>
<td class="bright weather-icon"><span class="wi weathericon wi-{{ f.weatherType }}"></span></td>
<td class="align-right bright max-temp">
{{f.maxTemperature | roundValue | unit("temperature")}}
{{ f.maxTemperature | roundValue | unit("temperature") }}
</td>
<td class="align-right min-temp">
{{f.minTemperature | roundValue | unit("temperature")}}
{{ f.minTemperature | roundValue | unit("temperature") }}
</td>
{% if config.showRainAmount %}
<td class="align-right bright rain">
{{f.rain | unit("rain")}}
{% if config.showPrecipitationAmount %}
<td class="align-right bright precipitation">
{{ f.precipitation | unit("precip") }}
</td>
{% endif %}
</tr>
{% set currentStep = currentStep + 1 %}
{% endfor %}
</table>
{% else %}
{{"LOADING" | translate}}
<div class="dimmed light small">
{{ "LOADING" | translate | safe }}
</div>
{% endif %}
<!-- Unclomment the line below to see the contents of the `current` object. -->
<!-- Uncomment the line below to see the contents of the `current` object. -->
<!-- <div style="word-wrap:break-word" class="xsmall dimmed">{{forecast | dump}}</div> -->

View File

@@ -85,7 +85,7 @@ Notify the delegate that new weather is available.
#### `fetchData(url, method, data)`
A convinience function to make requests. It returns a promise.
A convenience function to make requests. It returns a promise.
### WeatherObject
@@ -103,6 +103,8 @@ A convinience function to make requests. It returns a promise.
| weatherType | `string` | Icon name of the weather type. <br> Possible values: [WeatherIcons](https://www.npmjs.com/package/weathericons) |
| humidity | `number` | Percentage of humidity |
| rain | `number` | Metric: `millimeters` <br> Imperial: `inches` |
| snow | `number` | Metric: `millimeters` <br> Imperial: `inches` |
| precipitation | `number` | Metric: `millimeters` <br> Imperial: `inches` |
#### Current weather

View File

@@ -8,6 +8,7 @@
* MIT Licensed
*
* This class is a provider for Dark Sky.
* Note that the Dark Sky API does not provide rainfall. Instead it provides snowfall and precipitation probability
*/
WeatherProvider.register("darksky", {
// Set the name of the provider.
@@ -81,12 +82,20 @@ WeatherProvider.register("darksky", {
weather.minTemperature = forecast.temperatureMin;
weather.maxTemperature = forecast.temperatureMax;
weather.weatherType = this.convertWeatherType(forecast.icon);
if (this.config.units === "metric" && !isNaN(forecast.precipAccumulation)) {
weather.rain = forecast.precipAccumulation * 10;
} else {
weather.rain = forecast.precipAccumulation;
weather.snow = 0;
// The API will return centimeters if units is 'si' and will return inches for 'us'
// Note that the Dark Sky API does not provide rainfall. Instead it provides snowfall and precipitation probability
if (forecast.hasOwnProperty("precipAccumulation")) {
if (this.config.units === "imperial" && !isNaN(forecast.precipAccumulation)) {
weather.snow = forecast.precipAccumulation;
} else if (!isNaN(forecast.precipAccumulation)) {
weather.snow = forecast.precipAccumulation * 10;
}
}
weather.precipitation = weather.snow;
days.push(weather);
}

View File

@@ -5,7 +5,7 @@
*
* By Michael Teeuw http://michaelteeuw.nl
* MIT Licensed.
*
*
* This class is the blueprint for a weather provider.
*/
@@ -56,8 +56,6 @@ WeatherProvider.register("openweathermap", {
})
},
/** OpenWeatherMap Specific Methods - These are not part of the default provider methods */
/*
* Gets the complete url for the request
@@ -66,7 +64,7 @@ WeatherProvider.register("openweathermap", {
return this.config.apiBase + this.config.apiVersion + this.config.weatherEndpoint + this.getParams();
},
/*
/*
* Generate a WeatherObject based on currentWeatherInformation
*/
generateWeatherObjectFromCurrentWeather(currentWeatherData) {
@@ -87,6 +85,105 @@ WeatherProvider.register("openweathermap", {
* Generate WeatherObjects based on forecast information
*/
generateWeatherObjectsFromForecast(forecasts) {
if (this.config.weatherEndpoint == "/forecast") {
return this.fetchForecastHourly(forecasts);
} else if (this.config.weatherEndpoint == "/forecast/daily") {
return this.fetchForecastDaily(forecasts);
}
// if weatherEndpoint does not match forecast or forecast/daily, what should be returned?
const days = [new WeatherObject(this.config.units)];
return days;
},
/*
* fetch forecast information for 3-hourly forecast (available for free subscription).
*/
fetchForecastHourly(forecasts) {
// initial variable declaration
const days = [];
// variables for temperature range and rain
let minTemp = [];
let maxTemp = [];
let rain = 0;
let snow = 0;
// variable for date
let date = "";
let weather = new WeatherObject(this.config.units);
for (const forecast of forecasts) {
if (date !== moment(forecast.dt, "X").format("YYYY-MM-DD")) {
// calculate minimum/maximum temperature, specify rain amount
weather.minTemperature = Math.min.apply(null, minTemp);
weather.maxTemperature = Math.max.apply(null, maxTemp);
weather.rain = rain;
weather.snow = snow;
weather.precipitation = weather.rain + weather.snow;
// push weather information to days array
days.push(weather);
// create new weather-object
weather = new WeatherObject(this.config.units);
minTemp = [];
maxTemp = [];
rain = 0;
snow = 0;
// set new date
date = moment(forecast.dt, "X").format("YYYY-MM-DD");
// specify date
weather.date = moment(forecast.dt, "X");
// If the first value of today is later than 17:00, we have an icon at least!
weather.weatherType = this.convertWeatherType(forecast.weather[0].icon);
}
if (moment(forecast.dt, "X").format("H") >= 8 && moment(forecast.dt, "X").format("H") <= 17) {
weather.weatherType = this.convertWeatherType(forecast.weather[0].icon);
}
// the same day as before
// add values from forecast to corresponding variables
minTemp.push(forecast.main.temp_min);
maxTemp.push(forecast.main.temp_max);
if (forecast.hasOwnProperty("rain")) {
if (this.config.units === "imperial" && !isNaN(forecast.rain["3h"])) {
rain += forecast.rain["3h"] / 25.4;
} else if (!isNaN(forecast.rain["3h"])) {
rain += forecast.rain["3h"];
}
}
if (forecast.hasOwnProperty("snow")) {
if (this.config.units === "imperial" && !isNaN(forecast.snow["3h"])) {
snow += forecast.snow["3h"] / 25.4;
} else if (!isNaN(forecast.snow["3h"])) {
snow += forecast.snow["3h"];
}
}
}
// last day
// calculate minimum/maximum temperature, specify rain amount
weather.minTemperature = Math.min.apply(null, minTemp);
weather.maxTemperature = Math.max.apply(null, maxTemp);
weather.rain = rain;
weather.snow = snow;
weather.precipitation = weather.rain + weather.snow;
// push weather information to days array
days.push(weather);
return days.slice(1);
},
/*
* fetch forecast information for daily forecast (available for paid subscription or old apiKey).
*/
fetchForecastDaily(forecasts) {
// initial variable declaration
const days = [];
for (const forecast of forecasts) {
@@ -96,16 +193,35 @@ WeatherProvider.register("openweathermap", {
weather.minTemperature = forecast.temp.min;
weather.maxTemperature = forecast.temp.max;
weather.weatherType = this.convertWeatherType(forecast.weather[0].icon);
if (this.config.units === "imperial" && !isNaN(forecast.rain)) {
weather.rain = forecast.rain / 25.4
} else {
weather.rain = forecast.rain;
weather.rain = 0;
weather.snow = 0;
// forecast.rain not available if amount is zero
// The API always returns in millimeters
if (forecast.hasOwnProperty("rain")) {
if (this.config.units === "imperial" && !isNaN(forecast.rain)) {
weather.rain = forecast.rain / 25.4;
} else if (!isNaN(forecast.rain)) {
weather.rain = forecast.rain;
}
}
// forecast.snow not available if amount is zero
// The API always returns in millimeters
if (forecast.hasOwnProperty("snow")) {
if (this.config.units === "imperial" && !isNaN(forecast.snow)) {
weather.snow = forecast.snow / 25.4;
} else if (!isNaN(forecast.snow)) {
weather.snow = forecast.snow;
}
}
weather.precipitation = weather.rain + weather.snow;
days.push(weather);
}
return days;
return days;
},
/*

View File

@@ -0,0 +1,256 @@
/* global WeatherProvider, WeatherObject */
/* Magic Mirror
* Module: Weather
* Provider: weather.gov
*
* By Vince Peri
* MIT Licensed.
*
* This class is a provider for weather.gov.
* Note that this is only for US locations (lat and lon) and does not require an API key
* Since it is free, there are some items missing - like sunrise, sunset, humidity, etc.
*/
WeatherProvider.register("weathergov", {
// Set the name of the provider.
// This isn't strictly necessary, since it will fallback to the provider identifier
// But for debugging (and future alerts) it would be nice to have the real name.
providerName: "Weather.gov",
// Overwrite the fetchCurrentWeather method.
fetchCurrentWeather() {
this.fetchData(this.getUrl())
.then(data => {
if (!data || !data.properties || !data.properties.periods || !data.properties.periods.length) {
// Did not receive usable new data.
// Maybe this needs a better check?
return;
}
const currentWeather = this.generateWeatherObjectFromCurrentWeather(data.properties.periods[0]);
this.setCurrentWeather(currentWeather);
})
.catch(function(request) {
Log.error("Could not load data ... ", request);
})
},
// Overwrite the fetchCurrentWeather method.
fetchWeatherForecast() {
this.fetchData(this.getUrl())
.then(data => {
if (!data || !data.properties || !data.properties.periods || !data.properties.periods.length) {
// Did not receive usable new data.
// Maybe this needs a better check?
return;
}
const forecast = this.generateWeatherObjectsFromForecast(data.properties.periods);
this.setWeatherForecast(forecast);
})
.catch(function(request) {
Log.error("Could not load data ... ", request);
})
},
/** Weather.gov Specific Methods - These are not part of the default provider methods */
/*
* Gets the complete url for the request
*/
getUrl() {
return this.config.apiBase + this.config.lat + "," + this.config.lon + this.config.weatherEndpoint;
},
/*
* Generate a WeatherObject based on currentWeatherInformation
*/
generateWeatherObjectFromCurrentWeather(currentWeatherData) {
const currentWeather = new WeatherObject(this.config.units);
currentWeather.temperature = currentWeatherData.temperature;
currentWeather.windSpeed = currentWeatherData.windSpeed.split(" ", 1);
currentWeather.windDirection = this.convertDirectiontoDegrees(currentWeatherData.windDirection);
currentWeather.weatherType = this.convertWeatherType(currentWeatherData.shortForecast, currentWeatherData.isDaytime);
return currentWeather;
},
/*
* Generate WeatherObjects based on forecast information
*/
generateWeatherObjectsFromForecast(forecasts) {
return this.fetchForecastDaily(forecasts);
},
/*
* fetch forecast information for daily forecast.
*/
fetchForecastDaily(forecasts) {
// initial variable declaration
const days = [];
// variables for temperature range and rain
let minTemp = [];
let maxTemp = [];
// variable for date
let date = "";
let weather = new WeatherObject(this.config.units);
weather.precipitation = 0;
for (const forecast of forecasts) {
if (date !== moment(forecast.startTime).format("YYYY-MM-DD")) {
// calculate minimum/maximum temperature, specify rain amount
weather.minTemperature = Math.min.apply(null, minTemp);
weather.maxTemperature = Math.max.apply(null, maxTemp);
// push weather information to days array
days.push(weather);
// create new weather-object
weather = new WeatherObject(this.config.units);
minTemp = [];
maxTemp = [];
weather.precipitation = 0;
// set new date
date = moment(forecast.startTime).format("YYYY-MM-DD");
// specify date
weather.date = moment(forecast.startTime);
// If the first value of today is later than 17:00, we have an icon at least!
weather.weatherType = this.convertWeatherType(forecast.shortForecast, forecast.isDaytime);
}
if (moment(forecast.startTime).format("H") >= 8 && moment(forecast.startTime).format("H") <= 17) {
weather.weatherType = this.convertWeatherType(forecast.shortForecast, forecast.isDaytime);
}
// the same day as before
// add values from forecast to corresponding variables
minTemp.push(forecast.temperature);
maxTemp.push(forecast.temperature);
}
// last day
// calculate minimum/maximum temperature, specify rain amount
weather.minTemperature = Math.min.apply(null, minTemp);
weather.maxTemperature = Math.max.apply(null, maxTemp);
// push weather information to days array
days.push(weather);
return days.slice(1);
},
/*
* Convert the icons to a more usable name.
*/
convertWeatherType(weatherType, isDaytime) {
//https://w1.weather.gov/xml/current_obs/weather.php
// There are way too many types to create, so lets just look for certain strings
if (weatherType.includes("Cloudy") || weatherType.includes("Partly")) {
if (isDaytime) {
return "day-cloudy";
}
return "night-cloudy";
} else if (weatherType.includes("Overcast")) {
if (isDaytime) {
return "cloudy";
}
return "night-cloudy";
} else if (weatherType.includes("Freezing") || weatherType.includes("Ice")) {
return "rain-mix";
} else if (weatherType.includes("Snow")) {
if (isDaytime) {
return "snow";
}
return "night-snow";
} else if (weatherType.includes("Thunderstorm")) {
if (isDaytime) {
return "thunderstorm";
}
return "night-thunderstorm";
} else if (weatherType.includes("Showers")) {
if (isDaytime) {
return "showers";
}
return "night-showers";
} else if (weatherType.includes("Rain") || weatherType.includes("Drizzle")) {
if (isDaytime) {
return "rain";
}
return "night-rain";
} else if (weatherType.includes("Breezy") || weatherType.includes("Windy")) {
if (isDaytime) {
return "cloudy-windy";
}
return "night-alt-cloudy-windy";
} else if (weatherType.includes("Fair") || weatherType.includes("Clear") || weatherType.includes("Few") || weatherType.includes("Sunny")) {
if (isDaytime) {
return "day-sunny";
}
return "night-clear";
} else if (weatherType.includes("Dust") || weatherType.includes("Sand")) {
return "dust";
} else if (weatherType.includes("Fog")) {
return "fog";
} else if (weatherType.includes("Smoke")) {
return "smoke";
} else if (weatherType.includes("Haze")) {
return "day-haze";
}
return null;
},
/*
Convert the direction into Degrees
*/
convertDirectiontoDegrees(direction) {
if (direction === "NNE"){
return 33.75;
} else if (direction === "NE") {
return 56.25;
} else if (direction === "ENE") {
return 78.75;
} else if (direction === "E") {
return 101.25;
} else if (direction === "ESE") {
return 123.75;
} else if (direction === "SE") {
return 146.25;
} else if (direction === "SSE") {
return 168.75;
} else if (direction === "S") {
return 191.25;
} else if (direction === "SSW") {
return 213.75;
} else if (direction === "SW") {
return 236.25;
} else if (direction === "WSW") {
return 258.75;
} else if (direction === "W") {
return 281.25;
} else if (direction === "WNW") {
return 303.75;
} else if (direction === "NW") {
return 326.25;
} else if (direction === "NNW") {
return 348.75;
} else {
return 0;
}
}
});

View File

@@ -31,11 +31,15 @@
padding-right: 0;
}
.weather .rain {
.weather .precipitation {
padding-left: 20px;
padding-right: 0;
}
.weather tr .weathericon {
line-height: 25px;
}
.weather tr.colored .min-temp {
color: #bcddff;
}

View File

@@ -30,8 +30,12 @@ Module.register("weather",{
lang: config.language,
showHumidity: false,
degreeLabel: false,
decimalSymbol: ".",
showIndoorTemperature: false,
showIndoorHumidity: false,
maxNumberOfDays: 5,
fade: true,
fadePoint: 0.25, // Start on 1/4th of the list.
initialLoadDelay: 0, // 0 seconds delay
retryDelay: 2500,
@@ -45,7 +49,7 @@ Module.register("weather",{
tableClass: "small",
onlyTemp: false,
showRainAmount: true,
showPrecipitationAmount: false,
colored: false,
showFeelsLike: true
},
@@ -58,7 +62,7 @@ Module.register("weather",{
return ["font-awesome.css", "weather-icons.css", "weather.css"];
},
// Return the scripts that are nessecery for the weather module.
// Return the scripts that are necessary for the weather module.
getScripts: function () {
return [
"moment.js",
@@ -184,7 +188,9 @@ Module.register("weather",{
this.nunjucksEnvironment().addFilter("unit", function (value, type) {
if (type === "temperature") {
value += "°";
if (this.config.units === "metric" || this.config.units === "imperial") {
value += "°";
}
if (this.config.degreeLabel) {
if (this.config.units === "metric") {
value += "C";
@@ -194,12 +200,14 @@ Module.register("weather",{
value += "K";
}
}
} else if (type === "rain") {
if (isNaN(value)) {
} else if (type === "precip") {
if (isNaN(value) || value === 0 || value.toFixed(2) === "0.00") {
value = "";
} else {
value = `${value.toFixed(2)} ${this.config.units === "imperial" ? "in" : "mm"}`;
}
} else if (type === "humidity") {
value += "%"
}
return value;
@@ -208,5 +216,30 @@ Module.register("weather",{
this.nunjucksEnvironment().addFilter("roundValue", function(value) {
return this.roundValue(value);
}.bind(this));
this.nunjucksEnvironment().addFilter("decimalSymbol", function(value) {
return value.toString().replace(/\./g, this.config.decimalSymbol);
}.bind(this));
this.nunjucksEnvironment().addFilter("calcNumSteps", function(forecast) {
return Math.min(forecast.length, this.config.maxNumberOfDays);
}.bind(this));
this.nunjucksEnvironment().addFilter("opacity", function(currentStep, numSteps) {
if (this.config.fade && this.config.fadePoint < 1) {
if (this.config.fadePoint < 0) {
this.config.fadePoint = 0;
}
var startingPoint = numSteps * this.config.fadePoint;
var numFadesteps = numSteps - startingPoint;
if (currentStep >= startingPoint) {
return 1 - (currentStep - startingPoint) / numFadesteps;
} else {
return 1;
}
} else {
return 1;
}
}.bind(this));
}
});

View File

@@ -26,6 +26,8 @@ class WeatherObject {
this.weatherType = null;
this.humidity = null;
this.rain = null;
this.snow = null;
this.precipitation = null;
}
cardinalWindDirection() {

View File

@@ -142,14 +142,17 @@ Module.register("weatherforecast",{
icon.className = "wi weathericon " + forecast.icon;
iconCell.appendChild(icon);
var degreeLabel = "&deg;";
var degreeLabel = "";
if (this.config.units === "metric" || this.config.units === "imperial") {
degreeLabel += "°";
}
if(this.config.scale) {
switch(this.config.units) {
case "metric":
degreeLabel += " C";
degreeLabel += "C";
break;
case "imperial":
degreeLabel += " F";
degreeLabel += "F";
break;
case "default":
degreeLabel = "K";

715
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "magicmirror",
"version": "2.6.0",
"version": "2.7.1",
"description": "The open source modular smart mirror platform.",
"main": "js/electron.js",
"scripts": {
@@ -58,7 +58,7 @@
"ajv": "6.5.5",
"body-parser": "^1.18.2",
"colors": "^1.1.2",
"electron": "^2.0.16",
"electron": "^3.0.13",
"express": "^4.16.2",
"express-ipfilter": "0.3.1",
"feedme": "latest",

View File

@@ -1,6 +1,5 @@
var app = require("../js/app.js");
app.start(function(config) {
console.log("");
var bindAddress = config.address ? config.address : "localhost";
console.log("Ready to go! Please point your browser to: http://" + bindAddress + ":" + config.port);
console.log("\nReady to go! Please point your browser to: http://" + bindAddress + ":" + config.port);
});

View File

@@ -36,7 +36,7 @@ describe("Electron app environment", function() {
it("should open a browserwindow", function() {
return app.client
.waitUntilWindowLoaded()
.browserWindow.focus()
// .browserWindow.focus()
.getWindowCount()
.should.eventually.equal(1)
.browserWindow.isMinimized()

View File

@@ -6,6 +6,8 @@
"DAYAFTERTOMORROW": "I overmorgen",
"RUNNING": "Slutter om",
"EMPTY": "Ingen kommende begivenheder.",
"FEELS": "Føles som",
"WEEK": "Uge {weekNumber}",
"N": "N",
"NNE": "NNØ",

View File

@@ -29,5 +29,7 @@
"UPDATE_NOTIFICATION": "E' disponibile un aggiornamento di MagicMirror².",
"UPDATE_NOTIFICATION_MODULE": "E' disponibile un aggiornamento del modulo {MODULE_NAME}.",
"UPDATE_INFO_SINGLE": "L'installazione è {COMMIT_COUNT} commit indietro rispetto all'attuale branch {BRANCH_NAME}.",
"UPDATE_INFO_MULTIPLE": "L'installazione è {COMMIT_COUNT} commits indietro rispetto all'attuale branch {BRANCH_NAME}."
"UPDATE_INFO_MULTIPLE": "L'installazione è {COMMIT_COUNT} commits indietro rispetto all'attuale branch {BRANCH_NAME}.",
"FEELS": "Percepiti"
}

33
translations/sk.json Normal file
View File

@@ -0,0 +1,33 @@
{
"LOADING": "Načítanie &hellip;",
"TODAY": "Dnes",
"TOMORROW": "Zajtra",
"DAYAFTERTOMORROW": "Pozajtra",
"RUNNING": "Končí o",
"EMPTY": "Žiadne nadchádzajúce udalosti.",
"WEEK": "{weekNumber}. týždeň",
"N": "S",
"NNE": "SSV",
"NE": "SV",
"ENE": "VSV",
"E": "V",
"ESE": "VJV",
"SE": "JV",
"SSE": "JJV",
"S": "J",
"SSW": "JJZ",
"SW": "JZ",
"WSW": "ZJZ",
"W": "Z",
"WNW": "ZSZ",
"NW": "SZ",
"NNW": "SSZ",
"UPDATE_NOTIFICATION": "Dostupná aktualizácia pre MagicMirror².",
"UPDATE_NOTIFICATION_MODULE": "Dostupná aktualizácia pre modul {MODULE_NAME}.",
"UPDATE_INFO_SINGLE": "Súčasná inštalácia je na vetve {BRANCH_NAME} pozadu o {COMMIT_COUNT} commit.",
"UPDATE_INFO_MULTIPLE": "Súčasná inštalácia je na vetve {BRANCH_NAME} pozadu o {COMMIT_COUNT} commitov."
}

35
translations/tlh.json Normal file
View File

@@ -0,0 +1,35 @@
{
"LOADING": "loS &hellip;",
"TODAY": "DaHjaj",
"TOMORROW": "wa'leS",
"DAYAFTERTOMORROW": "cha'leS",
"RUNNING": "Dor",
"EMPTY": "Sumbe' wanI'.",
"WEEK": "Hogh (terran) {weekNumber}",
"N": "N",
"NNE": "NNE",
"NE": "NE",
"ENE": "ENE",
"E": "chan",
"ESE": "ESE",
"SE": "SE",
"SSE": "SSE",
"S": "S",
"SSW": "SSW",
"SW": "tIng",
"WSW": "WSW",
"W": "W",
"WNW": "WNW",
"NW": "'ev",
"NNW": "NNW",
"UPDATE_NOTIFICATION": " De'chu' MagicMirror² lI'laH.",
"UPDATE_NOTIFICATION_MODULE": "bobcho' {MODULE_NAME} lI'laH De'chu.",
"UPDATE_INFO_SINGLE": "The current installation is {COMMIT_COUNT} commit behind on the {BRANCH_NAME} branch.",
"UPDATE_INFO_MULTIPLE": "The current installation is {COMMIT_COUNT} commits behind on the {BRANCH_NAME} branch.",
"FEELS": "jem"
}

View File

@@ -38,7 +38,9 @@ var translations = {
"cy" : "translations/cy.json", // Welsh (Cymraeg)
"bg" : "translations/bg.json", // Bulgarian
"cs" : "translations/cs.json", // Czech
"hr" : "translations/hr.json" // Croatian
"hr" : "translations/hr.json", // Croatian
"sk" : "translations/sk.json", // Slovak
"tlh" : "translations/tlh.json" // Klingon
};
if (typeof module !== "undefined") {module.exports = translations;}

2
vendor/css/font-awesome.css vendored Normal file
View File

@@ -0,0 +1,2 @@
@import url("../node_modules/@fortawesome/fontawesome-free/css/all.min.css");
@import url("../node_modules/@fortawesome/fontawesome-free/css/v4-shims.min.css");

71
vendor/package-lock.json generated vendored
View File

@@ -193,11 +193,6 @@
"repeat-string": "^1.5.2"
}
},
"font-awesome": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
"integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM="
},
"for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -230,7 +225,8 @@
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true
"bundled": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@@ -248,11 +244,13 @@
},
"balanced-match": {
"version": "1.0.0",
"bundled": true
"bundled": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -265,15 +263,18 @@
},
"code-point-at": {
"version": "1.1.0",
"bundled": true
"bundled": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true
"bundled": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true
"bundled": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -376,7 +377,8 @@
},
"inherits": {
"version": "2.0.3",
"bundled": true
"bundled": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@@ -386,6 +388,7 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -398,17 +401,20 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"bundled": true
"bundled": true,
"optional": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -425,6 +431,7 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -497,7 +504,8 @@
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true
"bundled": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -507,6 +515,7 @@
"once": {
"version": "1.4.0",
"bundled": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@@ -582,7 +591,8 @@
},
"safe-buffer": {
"version": "5.1.1",
"bundled": true
"bundled": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -612,6 +622,7 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -629,6 +640,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -667,11 +679,13 @@
},
"wrappy": {
"version": "1.0.2",
"bundled": true
"bundled": true,
"optional": true
},
"yallist": {
"version": "3.0.2",
"bundled": true
"bundled": true,
"optional": true
}
}
},
@@ -689,6 +703,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
"integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
"optional": true,
"requires": {
"is-glob": "^2.0.0"
}
@@ -702,7 +717,8 @@
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"optional": true
},
"invert-kv": {
"version": "1.0.0",
@@ -721,7 +737,8 @@
"is-buffer": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz",
"integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw="
"integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=",
"optional": true
},
"is-dotfile": {
"version": "1.0.3",
@@ -747,7 +764,8 @@
"is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
"integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
"integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
"optional": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
@@ -761,6 +779,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
"integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
"optional": true,
"requires": {
"is-extglob": "^1.0.0"
}
@@ -789,7 +808,8 @@
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"optional": true
},
"isobject": {
"version": "2.1.0",
@@ -804,6 +824,7 @@
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"optional": true,
"requires": {
"is-buffer": "^1.1.5"
}
@@ -869,6 +890,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
"integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
"optional": true,
"requires": {
"remove-trailing-separator": "^1.0.1"
}
@@ -1017,12 +1039,14 @@
"remove-trailing-separator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
"optional": true
},
"repeat-element": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
"integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo="
"integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=",
"optional": true
},
"repeat-string": {
"version": "1.6.1",
@@ -1033,7 +1057,8 @@
"safe-buffer": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
"optional": true
},
"set-immediate-shim": {
"version": "1.0.1",

1
vendor/package.json vendored
View File

@@ -11,7 +11,6 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.3.1",
"font-awesome": "^4.7.0",
"moment": "^2.17.1",
"moment-timezone": "^0.5.11",
"nunjucks": "^3.0.1",

4
vendor/vendor.js vendored
View File

@@ -12,9 +12,7 @@ var vendor = {
"moment-timezone.js" : "node_modules/moment-timezone/builds/moment-timezone-with-data.js",
"weather-icons.css": "node_modules/weathericons/css/weather-icons.css",
"weather-icons-wind.css": "node_modules/weathericons/css/weather-icons-wind.css",
"font-awesome.css": "node_modules/font-awesome/css/font-awesome.min.css",
"font-awesome5.css": "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
"font-awesome5.v4shims.css": "node_modules/@fortawesome/fontawesome-free/css/v4-shims.min.css",
"font-awesome.css": "css/font-awesome.css",
"nunjucks.js": "node_modules/nunjucks/browser/nunjucks.min.js"
};