Merge branch 'develop' of github.com:MichMich/MagicMirror into fix-timeshift-calendar
21
.github/ISSUE_TEMPLATE.md
vendored
@ -1,15 +1,28 @@
|
||||
Please only submit reproducible issues.
|
||||
|
||||
## I'm not sure if this is a bug
|
||||
If you're not sure if it's a real bug or if it's just you, please open a topic on the forum: [https://forum.magicmirror.builders/category/15/bug-hunt](https://forum.magicmirror.builders/category/15/bug-hunt)
|
||||
|
||||
## I'm having troubles installing or configuring MagicMirror
|
||||
Problems installing or configuring your MagicMirror? Check out: [https://forum.magicmirror.builders/category/10/troubleshooting](https://forum.magicmirror.builders/category/10/troubleshooting)
|
||||
|
||||
## I found a bug in the MagicMirror installer
|
||||
If you are facing an issue or found a bug while trying to install MagicMirror via the installer please report it in the respective GitHub repository:
|
||||
[https://github.com/sdetweil/MagicMirror_scripts](https://github.com/sdetweil/MagicMirror_scripts)
|
||||
|
||||
## I found a bug in the MagicMirror Docker image
|
||||
If you are facing an issue or found a bug while running MagicMirror inside a Docker container please create an issue in the GitHub repository of the MagicMirror Docker image:
|
||||
[https://github.com/bastilimbach/docker-MagicMirror](https://github.com/bastilimbach/docker-MagicMirror)
|
||||
|
||||
---
|
||||
|
||||
## I found a bug in MagicMirror
|
||||
Please make sure to only submit reproducible issues. You can safely remove everything above the dividing line.
|
||||
When submitting a new issue, please supply the following information:
|
||||
|
||||
**Platform**: Place your platform here... give us your web browser/Electron version *and* your hardware (Raspberry Pi 2/3, Windows, Mac, Linux, System V UNIX).
|
||||
|
||||
**Node Version**: Make sure it's version 0.12.13 or later.
|
||||
**Node Version**: Make sure it's version 8 or later.
|
||||
|
||||
**MagicMirror Version**: Now that the versions have split, tell us if you are using the PHP version (v1) or the newer JavaScript version (v2).
|
||||
**MagicMirror Version**: Please let us now which version of MagicMirror you are running. It can be found in the `package.log` file.
|
||||
|
||||
**Description**: Provide a detailed description about the issue and include specific details to help us understand the problem. Adding screenshots will help describing the problem.
|
||||
|
||||
|
25
CHANGELOG.md
@ -5,6 +5,23 @@ 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.11.0] - Unreleased (Develop Branch)
|
||||
|
||||
*This release is scheduled to be released on 2020-04-01.*
|
||||
|
||||
### Deleted
|
||||
- cleanup installers folder, remove externalized scripts
|
||||
|
||||
### Added
|
||||
- Finnish translation for "PRECIP", "UPDATE_INFO_MULTIPLE" and "UPDATE_INFO_SINGLE".
|
||||
|
||||
### Fixed
|
||||
- Force declaration of public ip adress in config file (ISSUE #1852)
|
||||
- Fixes `run-start.sh`: If running in docker-container, don't check the environment, just start electron (ISSUE #1859)
|
||||
|
||||
### Updated
|
||||
- Remove documentation from core repository and link to new dedicated docs site: [docs.magicmirror.builders](https://docs.magicmirror.builders).
|
||||
|
||||
## [2.10.1] - 2020-01-10
|
||||
|
||||
### Changed
|
||||
@ -12,6 +29,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [2.10.0] - 2020-01-01
|
||||
|
||||
Special thanks to @sdetweil for all his great contributions!
|
||||
|
||||
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`.
|
||||
|
||||
### Added
|
||||
@ -32,9 +51,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- Fixed issue in weatherforecast module where predicted amount of rain was not using the decimal symbol specified in config.js.
|
||||
- Module header now updates correctly, if a module need to dynamically show/hide its header based on a condition.
|
||||
- Fix handling of config.js for serverOnly mode commented out.
|
||||
- Fixed issue in calendar module where the debug script didn't work correctly with authentication
|
||||
- Fixed issue that some full day events were not correctly recognized as such
|
||||
- Display full day events lasting multiple days as happening today instead of some days ago if they are still ongoing
|
||||
- Fixed issue in calendar module where the debug script didn't work correctly with authentication.
|
||||
- Fixed issue that some full day events were not correctly recognized as such.
|
||||
- Display full day events lasting multiple days as happening today instead of some days ago if they are still ongoing.
|
||||
|
||||
## [2.9.0] - 2019-10-01
|
||||
|
||||
|
@ -12,8 +12,8 @@ var config = {
|
||||
address: "localhost", // Address to listen on, can be:
|
||||
// - "localhost", "127.0.0.1", "::1" to listen on loopback interface
|
||||
// - another specific IPv4/6 to listen on a specific interface
|
||||
// - "", "0.0.0.0", "::" to listen on any interface
|
||||
// Default, when address config is left out, is "localhost"
|
||||
// - "0.0.0.0", "::" to listen on any interface
|
||||
// Default, when address config is left out or empty, is "localhost"
|
||||
port: 8080,
|
||||
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], // Set [] to allow all IP addresses
|
||||
// or add a specific IPv4 of 192.168.1.5 :
|
||||
|
@ -1,15 +0,0 @@
|
||||
const config = require('../config/config.js');const fs=require('fs');
|
||||
for(let m of config.modules){
|
||||
if(!(m.disabled || false)){
|
||||
try {
|
||||
let f=fs.statSync(m.module);
|
||||
if(f.isDirectory()){
|
||||
f1=fs.statSync(m.module+'/package.json');
|
||||
if (f1.isFile()){
|
||||
console.log(m.module);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ex) {}
|
||||
}
|
||||
}
|
@ -1,183 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Define the tested version of Node.js.
|
||||
NODE_TESTED="v10.1.0"
|
||||
NPM_TESTED="V6.0.0"
|
||||
USER=`whoami`
|
||||
PM2_FILE=pm2_MagicMirror.json
|
||||
mac=$(uname -s)
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
cmd=greadlink
|
||||
else
|
||||
cmd=readlink
|
||||
fi
|
||||
|
||||
if [ -d ~/MagicMirror ]; then
|
||||
# put the log where the script is located
|
||||
logdir=$(dirname $($cmd -f "$0"))
|
||||
# if the script was execute from the web
|
||||
if [[ $logdir != *"MagicMirror/installers"* ]]; then
|
||||
# use the MagicMirror/installers folder
|
||||
cd ~/MagicMirror/installers >/dev/null
|
||||
logdir=$(pwd)
|
||||
cd - >/dev/null
|
||||
fi
|
||||
logfile=$logdir/pm2_setup.log
|
||||
echo the log will be saved in $logfile
|
||||
date +"pm2 setup starting - %a %b %e %H:%M:%S %Z %Y" >>$logfile
|
||||
echo system is $(uname -a) >> $logfile
|
||||
if [ "$mac" == "Darwin" ]; then
|
||||
echo the os is macOS $(sw_vers -productVersion) >> $logfile
|
||||
else
|
||||
echo the os is $(lsb_release -a 2>/dev/null) >> $logfile
|
||||
fi
|
||||
node_installed=$(which node)
|
||||
if [ "$node_installed." == "." ]; then
|
||||
# node not installed
|
||||
echo Installing node >>$logfile
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
brew install node
|
||||
else
|
||||
NODE_STABLE_BRANCH="10.x"
|
||||
curl -sL https://deb.nodesource.com/setup_$NODE_STABLE_BRANCH | sudo -E bash -
|
||||
sudo apt-get install -y nodejs
|
||||
fi
|
||||
fi
|
||||
node_version=$(node -v)
|
||||
echo node version $node_version >>$logfile
|
||||
npm_installed=$(which npm)
|
||||
if [ "$npm_installed." == "." ]; then
|
||||
# npm not installed
|
||||
echo Installing npm >>$logfile
|
||||
if [ $mac != 'Darwin' ]; then
|
||||
sudo apt-get install -y npm
|
||||
fi
|
||||
fi
|
||||
# get latest
|
||||
echo force installing latest npm version via npm >>$logfile
|
||||
#sudo npm i -g npm
|
||||
npm_version=$(npm -v)
|
||||
echo npm version $npm_version >>$logfile
|
||||
# assume pm2 will be found on the path
|
||||
pm2cmd=pm2
|
||||
up=""
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
up="--unsafe-perm"
|
||||
launchctl=launchctl
|
||||
launchctl_path=$(which $launchctl)
|
||||
`export PATH=$PATH:${launchctl_path%/$launchctl}`
|
||||
fi
|
||||
# check to see if already installed
|
||||
pm2_installed=$(which $pm2cmd)
|
||||
if [ "$pm2_installed." != "." ]; then
|
||||
# does it work?
|
||||
echo pm2 installed >> $logfile
|
||||
pm2_fails=$(pm2 list | grep -i -m 1 "App Name" | wc -l )
|
||||
if [ $pm2_fails != 1 ]; then
|
||||
# uninstall it
|
||||
echo pm2 installed, but does not work, uninstalling >> $logfile
|
||||
sudo npm uninstall $up -g pm2
|
||||
# force reinstall
|
||||
pm2_installed=
|
||||
fi
|
||||
fi
|
||||
# in not installed
|
||||
if [ "$pm2_installed." == "." ]; then
|
||||
# install it.
|
||||
echo pm2 not installed, installing >>$logfile
|
||||
result=$(sudo npm install $up -g pm2)
|
||||
# if this is a mac
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
echo this is a mac, fixup for path >>$logfile
|
||||
# get the location of pm2 install
|
||||
# parse the npm install output to get the command
|
||||
pm2cmd=`echo $result | awk -F - '{print $1}' | tr -d '[:space:]'`
|
||||
c='/pm2'
|
||||
# get the path only
|
||||
echo ${pm2cmd%$c} >installers/pm2path
|
||||
fi
|
||||
fi
|
||||
# remove MagicMirror if defined
|
||||
$pm2cmd delete MagicMirror >/dev/null 2>&1
|
||||
cd ~/MagicMirror
|
||||
echo get the pm2 platform specific startup command >>$logfile
|
||||
# get the platform specific pm2 startup command
|
||||
v=$($pm2cmd startup | tail -n 1)
|
||||
if [ $mac != 'Darwin' ]; then
|
||||
# check to see if we can get the OS package name (Ubuntu)
|
||||
if [ $(which lsb_release| wc -l) >0 ]; then
|
||||
# fix command
|
||||
# if ubuntu 18.04, pm2 startup gets something wrong
|
||||
if [ $(lsb_release -r | grep -m1 18.04 | wc -l) > 0 ]; then
|
||||
v=$(echo $v | sed 's/\/bin/\/bin:\/bin/')
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
echo startup command = $v >>$logfile
|
||||
# execute the command returned
|
||||
$v 2>&1 >>$logfile
|
||||
echo pm2 startup command done >>$logfile
|
||||
# is this is mac
|
||||
# need to fix pm2 startup, only on catalina
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
if [ $(sw_vers -productVersion | head -c 6) == '10.15.' ]; then
|
||||
# only do if the faulty tag is present (pm2 may fix this, before the script is fixed)
|
||||
if [ $(grep -m 1 UserName /Users/$USER/Library/LaunchAgents/pm2.$USER.plist | wc -l) -eq 1 ]; then
|
||||
# copy the pm2 startup file config
|
||||
cp /Users/$USER/Library/LaunchAgents/pm2.$USER.plist .
|
||||
# edit out the UserName key/value strings
|
||||
sed -e '/UserName/{N;d;}' pm2.$USER.plist > pm2.$USER.plist.new
|
||||
# copy the file back
|
||||
sudo cp pm2.$USER.plist.new /Users/$USER/Library/LaunchAgents/pm2.$USER.plist
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# if the user is no pi, we have to fixup the pm2 json file
|
||||
echo configure the pm2 config file for MagicMirror >>$logfile
|
||||
if [ "$USER" != "pi" ]; then
|
||||
echo the user is not pi >>$logfile
|
||||
# go to the installers folder`
|
||||
cd installers
|
||||
# edit the startup script for the right user
|
||||
echo change mm.sh >>$logfile
|
||||
if [ ! -e mm_temp.sh ]; then
|
||||
echo save copy of mm.sh >> $logfile
|
||||
cp mm.sh mm_temp.sh
|
||||
fi
|
||||
if [ $(grep pi mm_temp.sh | wc -l) -gt 0 ]; then
|
||||
echo change hard coded pi username >> $logfile
|
||||
sed 's/pi/'$USER'/g' mm_temp.sh >mm.sh
|
||||
else
|
||||
echo change relative home path to hard coded path >> $logfile
|
||||
hf=$(echo $HOME |sed 's/\//\\\//g')
|
||||
sed 's/\~/'$hf'/g' mm_temp.sh >mm.sh
|
||||
fi
|
||||
# edit the pms config file for the right user
|
||||
echo change $PM2_FILE >>$logfile
|
||||
sed 's/pi/'$USER'/g' $PM2_FILE > pm2_MagicMirror_new.json
|
||||
# make sure to use the updated file
|
||||
PM2_FILE=pm2_MagicMirror_new.json
|
||||
# if this is a mac
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
# copy the path file to the system paths list
|
||||
sudo cp ./pm2path /etc/paths.d
|
||||
# change the name of the home path for mac
|
||||
sed 's/home/Users/g' $PM2_FILE > pm2_MagicMirror_new1.json
|
||||
# make sure to use the updated file
|
||||
PM2_FILE=pm2_MagicMirror_new1.json
|
||||
fi
|
||||
echo now using this config file $PM2_FILE >>$logfile
|
||||
# go back one cd level
|
||||
cd - >/dev/null
|
||||
fi
|
||||
echo start MagicMirror via pm2 now >>$logfile
|
||||
# tell pm2 to start the app defined in the config file
|
||||
$pm2cmd start $HOME/MagicMirror/installers/$PM2_FILE
|
||||
# tell pm2 to save that configuration, for start at boot
|
||||
echo save MagicMirror pm2 config now >>$logfile
|
||||
$pm2cmd save
|
||||
date +"pm2 setup completed - %a %b %e %H:%M:%S %Z %Y" >>$logfile
|
||||
else
|
||||
echo It appears MagicMirror has not been installed on this system
|
||||
echo please run the installer, "raspberry.sh" first
|
||||
fi
|
@ -1,2 +0,0 @@
|
||||
cd ~/MagicMirror
|
||||
DISPLAY=:0 npm start
|
@ -1,569 +0,0 @@
|
||||
#!/bin/bash
|
||||
# This is an installer script for MagicMirror2. It works well enough
|
||||
# that it can detect if you have Node installed, run a binary script
|
||||
# and then download and run MagicMirror2.
|
||||
|
||||
if [ $USER == 'root' ]; then
|
||||
echo Please logon as a user to execute the MagicMirror installation, not root
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "\e[0m"
|
||||
echo '$$\ $$\ $$\ $$\ $$\ $$\ $$$$$$\'
|
||||
echo '$$$\ $$$ | \__| $$$\ $$$ |\__| $$ __$$\'
|
||||
echo '$$$$\ $$$$ | $$$$$$\ $$$$$$\ $$\ $$$$$$$\ $$$$\ $$$$ |$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ \__/ $$ |'
|
||||
echo '$$\$$\$$ $$ | \____$$\ $$ __$$\ $$ |$$ _____|$$\$$\$$ $$ |$$ |$$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ $$$$$$ |'
|
||||
echo '$$ \$$$ $$ | $$$$$$$ |$$ / $$ |$$ |$$ / $$ \$$$ $$ |$$ |$$ | \__|$$ | \__|$$ / $$ |$$ | \__|$$ ____/'
|
||||
echo '$$ |\$ /$$ |$$ __$$ |$$ | $$ |$$ |$$ | $$ |\$ /$$ |$$ |$$ | $$ | $$ | $$ |$$ | $$ |'
|
||||
echo '$$ | \_/ $$ |\$$$$$$$ |\$$$$$$$ |$$ |\$$$$$$$\ $$ | \_/ $$ |$$ |$$ | $$ | \$$$$$$ |$$ | $$$$$$$$\'
|
||||
echo '\__| \__| \_______| \____$$ |\__| \_______|\__| \__|\__|\__| \__| \______/ \__| \________|'
|
||||
echo ' $$\ $$ |'
|
||||
echo ' \$$$$$$ |'
|
||||
echo ' \______/'
|
||||
echo -e "\e[0m"
|
||||
|
||||
doInstall=1
|
||||
true=1
|
||||
false=0
|
||||
# Define the tested version of Node.js.
|
||||
NODE_TESTED="v10.1.0"
|
||||
NPM_TESTED="V6.0.0"
|
||||
USER=`whoami`
|
||||
PM2_FILE=pm2_MagicMirror.json
|
||||
force_arch=
|
||||
pm2setup=$false
|
||||
|
||||
trim() {
|
||||
local var="$*"
|
||||
# remove leading whitespace characters
|
||||
var="${var#"${var%%[![:space:]]*}"}"
|
||||
# remove trailing whitespace characters
|
||||
var="${var%"${var##*[![:space:]]}"}"
|
||||
echo -n "$var"
|
||||
}
|
||||
|
||||
|
||||
|
||||
mac=$(uname -s)
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
echo this is a mac | tee -a $logfile
|
||||
cmd=greadlink
|
||||
else
|
||||
cmd=readlink
|
||||
fi
|
||||
|
||||
|
||||
# put the log where the script is located
|
||||
logdir=$(dirname $($cmd -f "$0"))
|
||||
# if the script was execute from the web
|
||||
if [[ $logdir != *"MagicMirror/installers"* ]]; then
|
||||
# use the MagicMirror/installers folder, if setup
|
||||
if [ -d MagicMirror ]; then
|
||||
cd ~/MagicMirror/installers >/dev/null
|
||||
logdir=$(pwd)
|
||||
cd - >/dev/null
|
||||
else
|
||||
# use the users home folder if initial install
|
||||
logdir=$HOME
|
||||
fi
|
||||
fi
|
||||
logfile=$logdir/install.log
|
||||
echo install log being saved to $logfile
|
||||
|
||||
# Determine which Pi is running.
|
||||
date +"install starting - %a %b %e %H:%M:%S %Z %Y" >>$logfile
|
||||
ARM=$(uname -m)
|
||||
echo installing on $ARM processor system >>$logfile
|
||||
echo the os is $(lsb_release -a 2>/dev/null) >> $logfile
|
||||
# Check the Raspberry Pi version.
|
||||
if [ "$ARM" != "armv7l" ]; then
|
||||
read -p "this appears not to be a Raspberry Pi 2 or 3, do you want to continue installation (y/N)?" choice
|
||||
if [[ $choice =~ ^[Nn]$ ]]; then
|
||||
echo user stopped install on $ARM hardware >>$logfile
|
||||
echo -e "\e[91mSorry, your Raspberry Pi is not supported."
|
||||
echo -e "\e[91mPlease run MagicMirror on a Raspberry Pi 2 or 3."
|
||||
echo -e "\e[91mIf this is a Pi Zero, the setup will configure to run in server only mode wih a local browser."
|
||||
exit;
|
||||
fi
|
||||
#if [ "$ARM" == "armv6l" ]; then
|
||||
# echo forcing armv71 architecture for pi 0 >>$logfile
|
||||
# force_arch=-'--arch=armv7l'
|
||||
# fi
|
||||
fi
|
||||
|
||||
# Define helper methods.
|
||||
function command_exists () { type "$1" &> /dev/null ;}
|
||||
function verlte() { [ "$1" = "`echo -e "$1\n$2" | sort -V | head -n1`" ];}
|
||||
function verlt() { [ "$1" = "$2" ] && return 1 || verlte $1 $2 ;}
|
||||
|
||||
# Update before first apt-get
|
||||
if [ $mac != 'Darwin' ]; then
|
||||
echo -e "\e[96mUpdating packages ...\e[90m" | tee -a $logfile
|
||||
upgrade=$false
|
||||
update=$(sudo apt-get update 2>&1)
|
||||
echo $update >> $logfile
|
||||
update_rc=$?
|
||||
if [ $update_rc -ne 0 ]; then
|
||||
echo -e "\e[91mUpdate failed, retrying installation ...\e[90m" | tee -a $logfile
|
||||
if [ $(echo $update | grep "apt-secure" | wc -l) -eq 1 ]; then
|
||||
update=$(sudo apt-get update --allow-releaseinfo-change 2>&1)
|
||||
update_rc=$?
|
||||
echo $update >> $logfile
|
||||
if [ $update_rc -ne 0 ]; then
|
||||
echo "second apt-get update failed" $update | tee -a $logfile
|
||||
exit 1
|
||||
else
|
||||
echo "second apt-get update completed ok" >> $logfile
|
||||
upgrade=$true
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "apt-get update completed ok" >> $logfile
|
||||
upgrade=$true
|
||||
fi
|
||||
if [ $upgrade -eq $true ]; then
|
||||
upgrade_result=$(sudo apt-get upgrade 2>&1)
|
||||
upgrade_rc=$?
|
||||
echo apt upgrade result ="rc=$upgrade_rc $upgrade_result" >> $logfile
|
||||
fi
|
||||
|
||||
# Installing helper tools
|
||||
echo -e "\e[96mInstalling helper tools ...\e[90m" | tee -a $logfile
|
||||
sudo apt-get --assume-yes install curl wget git build-essential unzip || exit
|
||||
fi
|
||||
|
||||
# Check if we need to install or upgrade Node.js.
|
||||
echo -e "\e[96mCheck current Node installation ...\e[0m" | tee -a $logfile
|
||||
NODE_INSTALL=false
|
||||
if command_exists node; then
|
||||
echo -e "\e[0mNode currently installed. Checking version number." | tee -a $logfile
|
||||
NODE_CURRENT=$(node -v)
|
||||
if [ "$NODE_CURRENT." == "." ]; then
|
||||
NODE_CURRENT="V1.0.0"
|
||||
echo forcing low Node version >> $logfile
|
||||
fi
|
||||
echo -e "\e[0mMinimum Node version: \e[1m$NODE_TESTED\e[0m" | tee -a $logfile
|
||||
echo -e "\e[0mInstalled Node version: \e[1m$NODE_CURRENT\e[0m" | tee -a $logfile
|
||||
if verlte $NODE_CURRENT $NODE_TESTED; then
|
||||
echo -e "\e[96mNode should be upgraded.\e[0m" | tee -a $logfile
|
||||
NODE_INSTALL=true
|
||||
|
||||
# Check if a node process is currenlty running.
|
||||
# If so abort installation.
|
||||
if pgrep "node" > /dev/null; then
|
||||
echo -e "\e[91mA Node process is currently running. Can't upgrade." | tee -a $logfile
|
||||
echo "Please quit all Node processes and restart the installer." | tee -a $logfile
|
||||
echo $(ps -ef | grep node | grep -v \-\-color) | tee -a $logfile
|
||||
exit;
|
||||
fi
|
||||
|
||||
else
|
||||
echo -e "\e[92mNo Node.js upgrade necessary.\e[0m" | tee -a $logfile
|
||||
fi
|
||||
|
||||
else
|
||||
echo -e "\e[93mNode.js is not installed.\e[0m" | tee -a $logfile
|
||||
NODE_INSTALL=true
|
||||
fi
|
||||
# Install or upgrade node if necessary.
|
||||
if $NODE_INSTALL; then
|
||||
|
||||
echo -e "\e[96mInstalling Node.js ...\e[90m" | tee -a $logfile
|
||||
|
||||
# Fetch the latest version of Node.js from the selected branch
|
||||
# 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.
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
brew install node
|
||||
else
|
||||
NODE_STABLE_BRANCH="10.x"
|
||||
# sudo apt-get install --only-upgrade libstdc++6
|
||||
node_info=$(curl -sL https://deb.nodesource.com/setup_$NODE_STABLE_BRANCH | sudo -E bash - )
|
||||
echo Node release info = $node_info >> $logfile
|
||||
if [ "$(echo $node_info | grep "not currently supported")." == "." ]; then
|
||||
sudo apt-get install -y nodejs
|
||||
else
|
||||
echo node $NODE_STABLE_BRANCH version installer not available, doing manually >>$logfile
|
||||
# no longer supported install
|
||||
sudo apt-get install -y --only-upgrade libstdc++6 >> $logfile
|
||||
# have to do it manually
|
||||
node_vnum=$(echo $NODE_STABLE_BRANCH | awk -F. '{print $1}')
|
||||
# get the highest release number in the stable branch line for this processor architecture
|
||||
node_ver=$(curl -sL https://unofficial-builds.nodejs.org/download/release/index.tab | grep $ARM | grep -m 1 v$node_vnum | awk '{print $1}')
|
||||
echo latest release in the $NODE_STABLE_BRANCH family for $ARM is $node_ver >> $logfile
|
||||
curl -sL https://unofficial-builds.nodejs.org/download/release/$node_ver/node-$node_ver-linux-$ARM.tar.gz >node_release-$node_ver.tar.gz
|
||||
cd /usr/local
|
||||
echo using release tar file = node_release-$node_ver.tar.gz >> $logfile
|
||||
sudo tar --strip-components 1 -xzf $HOME/node_release-$node_ver.tar.gz
|
||||
cd - >/dev/null
|
||||
rm ./node_release-$node_ver.tar.gz
|
||||
fi
|
||||
# get the new node version number
|
||||
new_ver=$(node -v 2>&1)
|
||||
# if there is a failure to get it due to a missing library
|
||||
if [ $(echo $new_ver | grep "not found" | wc -l) -ne 0 ]; then
|
||||
#
|
||||
sudo apt-get install -y --only-upgrade libstdc++6 >> $logfile
|
||||
fi
|
||||
echo node version is $(node -v 2>&1 >>$logfile)
|
||||
fi
|
||||
echo -e "\e[92mNode.js installation Done! version=$(node -v)\e[0m" | tee -a $logfile
|
||||
fi
|
||||
# Check if we need to install or upgrade npm.
|
||||
echo -e "\e[96mCheck current NPM installation ...\e[0m" | tee -a $logfile
|
||||
NPM_INSTALL=false
|
||||
if command_exists npm; then
|
||||
echo -e "\e[0mNPM currently installed. Checking version number." | tee -a $logfile
|
||||
NPM_CURRENT='V'$(npm -v)
|
||||
echo -e "\e[0mMinimum npm version: \e[1m$NPM_TESTED\e[0m" | tee -a $logfile
|
||||
echo -e "\e[0mInstalled npm version: \e[1m$NPM_CURRENT\e[0m" | tee -a $logfile
|
||||
if verlte $NPM_CURRENT $NPM_TESTED; then
|
||||
echo -e "\e[96mnpm should be upgraded.\e[0m" | tee -a $logfile
|
||||
NPM_INSTALL=true
|
||||
|
||||
# Check if a node process is currently running.
|
||||
# If so abort installation.
|
||||
if pgrep "npm" > /dev/null; then
|
||||
echo -e "\e[91mA npm process is currently running. Can't upgrade." | tee -a $logfile
|
||||
echo "Please quit all npm processes and restart the installer." | tee -a $logfile
|
||||
exit;
|
||||
fi
|
||||
|
||||
else
|
||||
echo -e "\e[92mNo npm upgrade necessary.\e[0m" | tee -a $logfile
|
||||
fi
|
||||
|
||||
else
|
||||
echo -e "\e[93mnpm is not installed.\e[0m" | tee -a $logfile
|
||||
NPM_INSTALL=true
|
||||
fi
|
||||
|
||||
# Install or upgrade node if necessary.
|
||||
if $NPM_INSTALL; then
|
||||
|
||||
echo -e "\e[96mInstalling npm ...\e[90m" | tee -a $logfile
|
||||
|
||||
# Fetch the latest version of npm from the selected branch
|
||||
# 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"
|
||||
#curl -sL https://deb.nodesource.com/setup_$NODE_STABLE_BRANCH | sudo -E bash -
|
||||
#
|
||||
# if this is a mac, npm was installed with node
|
||||
if [ $mac != 'Darwin' ]; then
|
||||
sudo apt-get install -y npm >>$logfile
|
||||
fi
|
||||
# update to the latest.
|
||||
echo upgrading npm to latest >> $logfile
|
||||
sudo npm i -g npm >>$logfile
|
||||
echo -e "\e[92mnpm installation Done! version=V$(npm -v)\e[0m" | tee -a $logfile
|
||||
fi
|
||||
|
||||
# Install MagicMirror
|
||||
cd ~
|
||||
if [ $doInstall == 1 ]; then
|
||||
if [ -d "$HOME/MagicMirror" ] ; then
|
||||
echo -e "\e[93mIt seems like MagicMirror is already installed." | tee -a $logfile
|
||||
echo -e "To prevent overwriting, the installer will be aborted." | tee -a $logfile
|
||||
echo -e "Please rename the \e[1m~/MagicMirror\e[0m\e[93m folder and try again.\e[0m" | tee -a $logfile
|
||||
echo ""
|
||||
echo -e "If you want to upgrade your installation run \e[1m\e[97mupgrade-script\e[0m from the ~/MagicMirror/installers directory." | tee -a $logfile
|
||||
echo ""
|
||||
exit;
|
||||
fi
|
||||
|
||||
echo -e "\e[96mCloning MagicMirror ...\e[90m" | tee -a $logfile
|
||||
if git clone --depth=1 https://github.com/MichMich/MagicMirror.git; then
|
||||
echo -e "\e[92mCloning MagicMirror Done!\e[0m" | tee -a $logfile
|
||||
else
|
||||
echo -e "\e[91mUnable to clone MagicMirror." | tee -a $logfile
|
||||
exit;
|
||||
fi
|
||||
|
||||
cd ~/MagicMirror || exit
|
||||
if [ $(grep version package.json | awk -F: '{print $2}') == '"2.9.0",' -a $ARM == 'armv6l' ]; then
|
||||
git fetch https://github.com/MichMich/MagicMirror.git develop >/dev/null 2>&1
|
||||
git branch develop FETCH_HEAD > /dev/null 2>&1
|
||||
git checkout develop > /dev/null 2>&1
|
||||
fi
|
||||
echo -e "\e[96mInstalling dependencies ...\e[90m" | tee -a $logfile
|
||||
if npm install $force_arch; then
|
||||
echo -e "\e[92mDependencies installation Done!\e[0m" | tee -a $logfile
|
||||
else
|
||||
echo -e "\e[91mUnable to install dependencies!" | tee -a $logfile
|
||||
exit;
|
||||
fi
|
||||
|
||||
# Use sample config for start MagicMirror
|
||||
echo setting up initial config.js | tee -a $logfile
|
||||
cp config/config.js.sample config/config.js
|
||||
fi
|
||||
# Check if plymouth is installed (default with PIXEL desktop environment), then install custom splashscreen.
|
||||
echo -e "\e[96mCheck plymouth installation ...\e[0m" | tee -a $logfile
|
||||
if command_exists plymouth; then
|
||||
THEME_DIR="/usr/share/plymouth/themes"
|
||||
echo -e "\e[90mSplashscreen: Checking themes directory.\e[0m" | tee -a $logfile
|
||||
if [ -d $THEME_DIR ]; then
|
||||
echo -e "\e[90mSplashscreen: Create theme directory if not exists.\e[0m" | tee -a $logfile
|
||||
if [ ! -d $THEME_DIR/MagicMirror ]; then
|
||||
sudo mkdir $THEME_DIR/MagicMirror
|
||||
fi
|
||||
|
||||
if sudo cp ~/MagicMirror/splashscreen/splash.png $THEME_DIR/MagicMirror/splash.png && sudo cp ~/MagicMirror/splashscreen/MagicMirror.plymouth $THEME_DIR/MagicMirror/MagicMirror.plymouth && sudo cp ~/MagicMirror/splashscreen/MagicMirror.script $THEME_DIR/MagicMirror/MagicMirror.script; then
|
||||
echo
|
||||
if [ "$(which plymouth-set-default-theme)." != "." ]; then
|
||||
if sudo plymouth-set-default-theme -R MagicMirror; then
|
||||
echo -e "\e[92mSplashscreen: Changed theme to MagicMirror successfully.\e[0m" | tee -a $logfile
|
||||
else
|
||||
echo -e "\e[91mSplashscreen: Couldn't change theme to MagicMirror!\e[0m" | tee -a $logfile
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo -e "\e[91mSplashscreen: Copying theme failed!\e[0m" | tee -a $logfile
|
||||
fi
|
||||
else
|
||||
echo -e "\e[91mSplashscreen: Themes folder doesn't exist!\e[0m" | tee -a $logfile
|
||||
fi
|
||||
else
|
||||
echo -e "\e[93mplymouth is not installed.\e[0m" | tee -a $logfile
|
||||
fi
|
||||
|
||||
# Use pm2 control like a service MagicMirror
|
||||
read -p "Do you want use pm2 for auto starting of your MagicMirror (y/N)?" choice
|
||||
if [[ $choice =~ ^[Yy]$ ]]; then
|
||||
echo install and setup pm2 | tee -a $logfile
|
||||
# assume pm2 will be found on the path
|
||||
pm2cmd=pm2
|
||||
# check to see if already installed
|
||||
pm2_installed=$(which $pm2cmd)
|
||||
up=""
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
up="--unsafe-perm"
|
||||
launchctl=launchctl
|
||||
launchctl_path=$(which $launchctl)
|
||||
`export PATH=$PATH:${launchctl_path%/$launchctl}`
|
||||
fi
|
||||
# check to see if already installed
|
||||
pm2_installed=$(which $pm2cmd)
|
||||
if [ "$pm2_installed." != "." ]; then
|
||||
# does it work?
|
||||
pm2_fails=$(pm2 list | grep -i -m 1 "App Name" | wc -l )
|
||||
if [ $pm2_fails != 1 ]; then
|
||||
# uninstall it
|
||||
echo pm2 installed, but does not work, uninstalling >> $logfile
|
||||
sudo npm uninstall $up -g pm2 >> $logfile
|
||||
# force reinstall
|
||||
pm2_installed=
|
||||
fi
|
||||
fi
|
||||
# if not installed
|
||||
if [ "$pm2_installed." == "." ]; then
|
||||
# install it.
|
||||
echo pm2 not installed, installing >>$logfile
|
||||
result=$(sudo npm install $up -g pm2 2>&1)
|
||||
echo pm2 install result $result >>$logfile
|
||||
# if this is a mac
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
echo this is a mac, fixup for path >>$logfile
|
||||
# get the location of pm2 install
|
||||
# parse the npm install output to get the command
|
||||
pm2cmd=`echo $result | awk -F - '{print $1}' | tr -d '[:space:]'`
|
||||
c='/pm2'
|
||||
# get the path only
|
||||
echo ${pm2cmd%$c} >installers/pm2path
|
||||
fi
|
||||
fi
|
||||
echo get the pm2 platform specific startup command >>$logfile
|
||||
# get the platform specific pm2 startup command
|
||||
v=$($pm2cmd startup | tail -n 1)
|
||||
if [ $mac != 'Darwin' ]; then
|
||||
# check to see if we can get the OS package name (Ubuntu)
|
||||
if [ $(which lsb_release| wc -l) >0 ]; then
|
||||
# fix command
|
||||
# if ubuntu 18.04, pm2 startup gets something wrong
|
||||
if [ $(lsb_release -r | grep -m1 18.04 | wc -l) > 0 ]; then
|
||||
v=$(echo $v | sed 's/\/bin/\/bin:\/bin/')
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
echo startup command = $v >>$logfile
|
||||
# execute the command returned
|
||||
$v 2>&1 >>$logfile
|
||||
echo pm2 startup command done >>$logfile
|
||||
# is this is mac
|
||||
# need to fix pm2 startup, only on catalina
|
||||
if [ $mac == 'Darwin' ];then
|
||||
if [ $(sw_vers -productVersion | head -c 6) == '10.15.' ]; then
|
||||
# only do if the faulty tag is present (pm2 may fix this, before the script is fixed)
|
||||
if [ $(grep -m 1 UserName /Users/$USER/Library/LaunchAgents/pm2.$USER.plist | wc -l) -eq 1 ]; then
|
||||
# copy the pm2 startup file config
|
||||
cp /Users/$USER/Library/LaunchAgents/pm2.$USER.plist .
|
||||
# edit out the UserName key/value strings
|
||||
sed -e '/UserName/{N;d;}' pm2.$USER.plist > pm2.$USER.plist.new
|
||||
# copy the file back
|
||||
sudo cp pm2.$USER.plist.new /Users/$USER/Library/LaunchAgents/pm2.$USER.plist
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
# if the user is no pi, we have to fixup the pm2 json file
|
||||
echo configure the pm2 config file for MagicMirror >>$logfile
|
||||
if [ "$USER" != "pi" ]; then
|
||||
echo the user is not pi >>$logfile
|
||||
# go to the installers folder`
|
||||
cd installers
|
||||
# edit the startup script for the right user
|
||||
echo change mm.sh >>$logfile
|
||||
if [ ! -e mm_temp.sh ]; then
|
||||
echo save copy of mm.sh >> $logfile
|
||||
cp mm.sh mm_temp.sh
|
||||
fi
|
||||
if [ $(grep pi mm_temp.sh | wc -l) -gt 0 ]; then
|
||||
echo change hard coded pi username >> $logfile
|
||||
sed 's/pi/'$USER'/g' mm_temp.sh >mm.sh
|
||||
else
|
||||
echo change relative home path to hard coded path >> $logfile
|
||||
hf=$(echo $HOME |sed 's/\//\\\//g')
|
||||
sed 's/\~/'$hf'/g' mm_temp.sh >mm.sh
|
||||
fi
|
||||
# edit the pms config file for the right user
|
||||
echo change $PM2_FILE >>$logfile
|
||||
sed 's/pi/'$USER'/g' $PM2_FILE > pm2_MagicMirror_new.json
|
||||
# make sure to use the updated file
|
||||
PM2_FILE=pm2_MagicMirror_new.json
|
||||
# if this is a mac
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
# copy the path file to the system paths list
|
||||
sudo cp ./pm2path /etc/paths.d
|
||||
# change the name of the home path for mac
|
||||
sed 's/home/Users/g' $PM2_FILE > pm2_MagicMirror_new1.json
|
||||
# make sure to use the updated file
|
||||
PM2_FILE=pm2_MagicMirror_new1.json
|
||||
fi
|
||||
echo now using this config file $PM2_FILE >>$logfile
|
||||
# go back one cd level
|
||||
cd - >/dev/null
|
||||
fi
|
||||
echo start MagicMirror via pm2 now >>$logfile
|
||||
# tell pm2 to start the app defined in the config file
|
||||
$pm2cmd start $HOME/MagicMirror/installers/$PM2_FILE
|
||||
# tell pm2 to save that configuration, for start at boot
|
||||
echo save MagicMirror pm2 config now >>$logfile
|
||||
$pm2cmd save
|
||||
pm2setup=$true
|
||||
fi
|
||||
# Disable Screensaver
|
||||
choice=n
|
||||
read -p "Do you want to disable the screen saver? (y/N)?" choice
|
||||
if [[ $choice =~ ^[Yy]$ ]]; then
|
||||
# if this is a mac
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
# get the current setting
|
||||
setting=$(defaults -currentHost read com.apple.screensaver idleTime)
|
||||
# if its on
|
||||
if [ $setting != 0 ] ; then
|
||||
# turn it off
|
||||
echo disable screensaver via mac profile >> $logfile
|
||||
defaults -currentHost write com.apple.screensaver idleTime 0
|
||||
else
|
||||
echo mac profile screen saver already disabled >> $logfile
|
||||
fi
|
||||
else
|
||||
# find out if some screen saver running
|
||||
|
||||
# get just the running processes and args
|
||||
# just want the program name (1st token)
|
||||
# find the 1st with 'saver' in it (should only be one)
|
||||
# parse with path char, get the last field ( the actual pgm name)
|
||||
|
||||
screen_saver_running=$(ps -A -o args | awk '{print $1}' | grep -m1 [s]aver | awk -F\/ '{print $NF}');
|
||||
|
||||
# if we found something
|
||||
if [ "$screen_saver_running." != "." ]; then
|
||||
# some screensaver running
|
||||
case "$screen_saver_running" in
|
||||
mate-screensaver) echo 'mate screen saver' >>$logfile
|
||||
#killall mate-screensaver >/dev/null 2>&1
|
||||
#$ms -d >/dev/null 2>&1
|
||||
gsettings set org.mate.screensaver lock-enabled false 2>/dev/null
|
||||
gsettings set org.mate.screensaver idle-activation-enabled false 2>/dev/null
|
||||
gsettings set org.mate.screensaver lock_delay 0 2>/dev/null
|
||||
echo " $screen_saver_running disabled" >> $logfile
|
||||
DISPLAY=:0 mate-screensaver >/dev/null 2>&1 &
|
||||
;;
|
||||
gnome-screensaver) echo 'gnome screen saver' >>$logfile
|
||||
gnome_screensaver-command -d >/dev/null 2>&1
|
||||
echo " $screen_saver_running disabled" >> $logfile
|
||||
;;
|
||||
xscreensaver) echo 'xscreensaver running' | tee -a $logfile
|
||||
if [ $(grep -m1 'mode:' ~/.xscreensaver | awk '{print $2}') != 'off' ]; then
|
||||
sed -i 's/$xsetting/mode: off/' ~/.xscreensaver
|
||||
echo " xscreensaver set to off" >> $logfile
|
||||
else
|
||||
echo " xscreensaver already disabled" >> $logfile
|
||||
fi
|
||||
;;
|
||||
gsd-screensaver | gsd-screensaver-proxy)
|
||||
setting=$(gsettings get org.gnome.desktop.screensaver lock-enabled)
|
||||
setting1=$(gsettings get org.gnome.desktop.session idle-delay)
|
||||
if [ "$setting $setting1" != 'false uint32 0' ]; then
|
||||
echo disable screensaver via gsettings was $setting and $setting1>> $logfile
|
||||
gsettings set org.gnome.desktop.screensaver lock-enabled false
|
||||
gsettings set org.gnome.desktop.screensaver idle-activation-enabled false
|
||||
gsettings set org.gnome.desktop.session idle-delay 0
|
||||
else
|
||||
echo gsettings screen saver already disabled >> $logfile
|
||||
fi
|
||||
;;
|
||||
*) echo "some other screensaver $screen_saver_running" found | tee -a $logfile
|
||||
echo "please configure it manually" | tee -a $logfile
|
||||
;;
|
||||
esac
|
||||
elif [ -e "/etc/lightdm/lightdm.conf" ]; then
|
||||
# if screen saver NOT already disabled?
|
||||
if [ $(grep 'xserver-command=X -s 0 -dpms' /etc/lightdm/lightdm.conf | wc -l) == 0 ]; then
|
||||
echo install screensaver via lightdm.conf >> $logfile
|
||||
sudo sed -i '/^\[Seat:\*\]/a xserver-command=X -s 0 -dpms' /etc/lightdm/lightdm.conf
|
||||
else
|
||||
echo screensaver via lightdm already disabled >> $logfile
|
||||
fi
|
||||
elif [ $(which gsettings | wc -l) == 1 ]; then
|
||||
setting=$(gsettings get org.gnome.desktop.screensaver lock-enabled)
|
||||
setting1=$(gsettings get org.gnome.desktop.session idle-delay)
|
||||
if [ "$setting $setting1" != 'false uint32 0' ]; then
|
||||
echo disable screensaver via gsettings was $setting and $setting1>> $logfile
|
||||
gsettings set org.gnome.desktop.screensaver lock-enabled false
|
||||
gsettings set org.gnome.desktop.screensaver idle-activation-enabled false
|
||||
gsettings set org.gnome.desktop.session idle-delay 0
|
||||
else
|
||||
echo gsettings screen saver already disabled >> $logfile
|
||||
fi
|
||||
elif [ -d "/etc/xdg/lxsession" ]; then
|
||||
currently_set=$(grep -m1 '\-dpms' /etc/xdg/lxsession/LXDE-pi/autostart)
|
||||
if [ "$currently_set." == "." ]; then
|
||||
echo disable screensaver via lxsession >> $logfile
|
||||
# turn it off for the future
|
||||
sudo su -c "echo -e '@xset s noblank\n@xset s off\n@xset -dpms' >> /etc/xdg/lxsession/LXDE-pi/autostart"
|
||||
# turn it off now
|
||||
export DISPLAY=:0; xset s noblank;xset s off;xset -dpms
|
||||
else
|
||||
echo lxsession screen saver already disabled >> $logfile
|
||||
fi
|
||||
else
|
||||
echo " "
|
||||
echo -e "unable to disable screen saver, /etc/xdg/lxsession does not exist" | tee -a $logfile
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
echo " "
|
||||
if [ $pm2setup -eq $true ]; then
|
||||
rmessage="pm2 start MagicMirror"
|
||||
else
|
||||
rmessage="DISPLAY=:0 npm start"
|
||||
fi
|
||||
echo -e "\e[92mWe're ready! Run \e[1m\e[97m$rmessage\e[0m\e[92m from the ~/MagicMirror directory to start your MagicMirror.\e[0m" | tee -a $logfile
|
||||
|
||||
echo " "
|
||||
echo " "
|
||||
|
||||
date +"install completed - %a %b %e %H:%M:%S %Z %Y" >>$logfile
|
@ -1,101 +0,0 @@
|
||||
#/bin/bash
|
||||
logfile=~/screensaver.log
|
||||
mac=$(uname -s)
|
||||
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
setting=$(defaults -currentHost read com.apple.screensaver idleTime)
|
||||
if [ $setting != 0 ] ; then
|
||||
echo disable screensaver via mac profile >> $logfile
|
||||
defaults -currentHost write com.apple.screensaver idleTime 0
|
||||
else
|
||||
echo mac profile screen saver already disabled >> $logfile
|
||||
fi
|
||||
else
|
||||
# find out if some screen saver running
|
||||
|
||||
# get just the running processes and args
|
||||
# just want the program name
|
||||
# find the 1st with 'saver' in it (should only be one)
|
||||
# if the process name is a path, parse it and get the last field ( the actual pgm name)
|
||||
|
||||
screen_saver_running=$(ps -A -o args | awk '{print $1}' | grep -m1 [s]aver | awk -F\/ '{print $NF}');
|
||||
|
||||
# if we found something
|
||||
if [ "$screen_saver_running." != "." ]; then
|
||||
# some screensaver running
|
||||
case "$screen_saver_running" in
|
||||
mate-screensaver) echo 'mate screen saver' >>$logfile
|
||||
#killall mate-screensaver >/dev/null 2>&1
|
||||
#ms=$(which mate-screensaver-command)
|
||||
#$ms -d >/dev/null 2>&1
|
||||
gsettings set org.mate.screensaver lock-enabled false 2>/dev/null
|
||||
gsettings set org.mate.screensaver idle-activation-enabled false 2>/dev/null
|
||||
gsettings set org.mate.screensaver lock_delay 0 2>/dev/null
|
||||
echo " $screen_saver_running disabled" >> $logfile
|
||||
DISPLAY=:0 mate-screensaver >/dev/null 2>&1 &
|
||||
;;
|
||||
gnome-screensaver) echo 'gnome screen saver' >>$logfile
|
||||
gnome_screensaver-command -d >/dev/null 2>&1
|
||||
echo " $screen_saver_running disabled" >> $logfile
|
||||
;;
|
||||
xscreensaver) echo 'xscreensaver running' | tee -a $logfile
|
||||
if [ $(grep -m1 'mode:' ~/.xscreensaver | awk '{print $2}') != 'off' ]; then
|
||||
sed -i 's/$xsetting/mode: off/' ~/.xscreensaver
|
||||
echo " xscreensaver set to off" >> $logfile
|
||||
else
|
||||
echo " xscreensaver already disabled" >> $logfile
|
||||
fi
|
||||
;;
|
||||
gsd-screensaver | gsd-screensaver-proxy)
|
||||
setting=$(gsettings get org.gnome.desktop.screensaver lock-enabled)
|
||||
setting1=$(gsettings get org.gnome.desktop.session idle-delay)
|
||||
if [ "$setting $setting1" != 'false uint32 0' ]; then
|
||||
echo disable screensaver via gsettings was $setting and $setting1>> $logfile
|
||||
gsettings set org.gnome.desktop.screensaver lock-enabled false
|
||||
gsettings set org.gnome.desktop.screensaver idle-activation-enabled false
|
||||
gsettings set org.gnome.desktop.session idle-delay 0
|
||||
else
|
||||
echo gsettings screen saver already disabled >> $logfile
|
||||
fi
|
||||
;;
|
||||
*) echo "some other screensaver $screen_saver_running" found | tee -a $logfile
|
||||
echo "please configure it manually" | tee -a $logfile
|
||||
;;
|
||||
esac
|
||||
elif [ -e "/etc/lightdm/lightdm.conf" ]; then
|
||||
# if screen saver NOT already disabled?
|
||||
if [ $(grep 'xserver-command=X -s 0 -dpms' /etc/lightdm/lightdm.conf | wc -l) == 0 ]; then
|
||||
echo install screensaver via lightdm.conf >> $logfile
|
||||
sudo sed -i '/^\[Seat:\*\]/a xserver-command=X -s 0 -dpms' /etc/lightdm/lightdm.conf
|
||||
#sudo cp _myconf /etc/lightdm/lightdm.conf
|
||||
#rm _myconf >/dev/null
|
||||
else
|
||||
echo screensaver via lightdm already disabled >> $logfile
|
||||
fi
|
||||
elif [ $(which gsettings | wc -l) == 1 ]; then
|
||||
setting=$(gsettings get org.gnome.desktop.screensaver lock-enabled)
|
||||
setting1=$(gsettings get org.gnome.desktop.session idle-delay)
|
||||
if [ "$setting $setting1" != 'false uint32 0' ]; then
|
||||
echo disable screensaver via gsettings was $setting and $setting1>> $logfile
|
||||
gsettings set org.gnome.desktop.screensaver lock-enabled false
|
||||
gsettings set org.gnome.desktop.screensaver idle-activation-enabled false
|
||||
gsettings set org.gnome.desktop.session idle-delay 0
|
||||
else
|
||||
echo gsettings screen saver already disabled >> $logfile
|
||||
fi
|
||||
elif [ -d "/etc/xdg/lxsession" ]; then
|
||||
currently_set=$(grep -m1 '\-dpms' /etc/xdg/lxsession/LXDE-pi/autostart)
|
||||
if [ "$currently_set." == "." ]; then
|
||||
echo disable screensaver via lxsession >> $logfile
|
||||
# turn it off for the future
|
||||
sudo su -c "echo -e '@xset s noblank\n@xset s off\n@xset -dpms' >> /etc/xdg/lxsession/LXDE-pi/autostart"
|
||||
# turn it off now
|
||||
export DISPLAY=:0; xset s noblank;xset s off;xset -dpms
|
||||
else
|
||||
echo lxsession screen saver already disabled >> $logfile
|
||||
fi
|
||||
else
|
||||
echo " "
|
||||
echo -e "unable to disable screen saver, /etc/xdg/lxsession does not exist" | tee >>$logfile
|
||||
fi
|
||||
fi
|
@ -1,361 +0,0 @@
|
||||
#!/bin/bash
|
||||
# only DO npm installs when flag is set to 1
|
||||
# test when set to 0
|
||||
true=1
|
||||
false=0
|
||||
doinstalls=$false
|
||||
force=$false
|
||||
justActive=$true
|
||||
test_run=$true
|
||||
stashed=$false
|
||||
keyFile=package.json
|
||||
forced_arch=
|
||||
git_active_lock='./.git/index.lock'
|
||||
lf=$'\n'
|
||||
git_user_name=
|
||||
git_user_email=
|
||||
|
||||
trim() {
|
||||
local var="$*"
|
||||
# remove leading whitespace characters
|
||||
var="${var#"${var%%[![:space:]]*}"}"
|
||||
# remove trailing whitespace characters
|
||||
var="${var%"${var##*[![:space:]]}"}"
|
||||
echo -n "$var"
|
||||
}
|
||||
# is this a mac
|
||||
mac=$(uname -s)
|
||||
# get the processor architecture
|
||||
arch=$(uname -m)
|
||||
if [ $mac == 'Darwin' ]; then
|
||||
cmd=greadlink
|
||||
else
|
||||
cmd=readlink
|
||||
fi
|
||||
if [ -d ~/MagicMirror ]; then
|
||||
|
||||
# put the log where the script is located
|
||||
logdir=$(dirname $($cmd -f "$0"))
|
||||
# if the script was execute from the web
|
||||
if [[ $logdir != *"MagicMirror/installers"* ]]; then
|
||||
# use the MagicMirror/installers folder
|
||||
cd ~/MagicMirror/installers >/dev/null
|
||||
logdir=$(pwd)
|
||||
cd - >/dev/null
|
||||
fi
|
||||
logfile=$logdir/upgrade.log
|
||||
echo the log will be $logfile
|
||||
echo >>$logfile
|
||||
date +"Upgrade started - %a %b %e %H:%M:%S %Z %Y" >>$logfile
|
||||
echo system is $(uname -a) >> $logfile
|
||||
echo the os is $(lsb_release -a) >> $logfile
|
||||
|
||||
# because of how its executed from the web, p0 gets overlayed with parm
|
||||
# check to see if a parm was passed .. easy apply without editing
|
||||
p0=$0
|
||||
# if not 'bash', and some parm specified
|
||||
if [ $0 != 'bash' -a "$1." != "." ]; then
|
||||
# then executed locally
|
||||
# get the parm
|
||||
p0=$1
|
||||
fi
|
||||
# lowercase it.. watch out, mac stuff doesn't work with tr, etc
|
||||
p0=$(echo $p0 | cut -c 1-5 | awk '{print tolower($0)}' )
|
||||
if [ $p0 == 'apply' ]; then
|
||||
echo user requested to apply changes >>$logfile
|
||||
doinstalls=$true
|
||||
test_run=$false
|
||||
elif [ $p0 == 'force' ]; then
|
||||
echo user requested to force apply changes >>$logfile
|
||||
doinstalls=$true
|
||||
force=$true
|
||||
test_run=$false
|
||||
fi
|
||||
|
||||
if [ $test_run == $true ]; then
|
||||
echo doing test run = true | tee -a $logfile
|
||||
else
|
||||
echo doing test run = false | tee -a $logfile
|
||||
fi
|
||||
|
||||
# if we want just the modules listed in config.js now
|
||||
if [ $justActive == $true ]; then
|
||||
if [ ! -f ~/MagicMirror/installers/dumpactivemodules.js ]; then
|
||||
echo downloading dumpactivemodules script >> $logfile
|
||||
curl -sL https://www.dropbox.com/s/wwe6bfg2lcjmj43/dumpactivemodules.js?dl=0 > ~/MagicMirror/installers/dumpactivemodules.js
|
||||
fi
|
||||
fi
|
||||
echo update log will be in $logfile
|
||||
# used for parsing the array of module names
|
||||
SAVEIFS=$IFS # Save current IFS
|
||||
IFS=$'\n'
|
||||
|
||||
echo | tee -a $logfile
|
||||
# if the git lock file exists and git is not running
|
||||
if [ -f git_active_lock ]; then
|
||||
# check to see if git is actually running
|
||||
git_running=`ps -ef | grep git | grep -v color | grep -v 'grep git' | wc -l`
|
||||
# if not running
|
||||
if [ git_running == $false ]; then
|
||||
# clean up the dangling lock file
|
||||
echo erasing abandonded git lock file >> $logfile
|
||||
rm git_active_lock >/dev/null 2>&1
|
||||
else
|
||||
# git IS running, we can't proceed
|
||||
echo it appears another instance of git is running | tee -a $logfile
|
||||
# if this is an actual run
|
||||
if [ $doinstalls == $true ]; then
|
||||
# force it back to test run
|
||||
doinstalls = $false
|
||||
test_run=$true
|
||||
echo forcing test run mode | tee -a $logfile
|
||||
echo please resolve git running already and start the update again | tee -a $logfile
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# change to MagicMirror folder
|
||||
cd ~/MagicMirror
|
||||
|
||||
# save custom.css
|
||||
cd css
|
||||
echo "saving custom.css" | tee -a $logfile
|
||||
cp -p custom.css save_custom.css
|
||||
cd - >/dev/null
|
||||
save_alias=$(alias git 2>/dev/null)
|
||||
lang=$(locale | grep LANGUAGE | awk -F= '{print $2}')
|
||||
# make sure git respones are in english, so code works
|
||||
if [ "$lang." != "en_US.UTF-8." ]; then
|
||||
echo not english or locale not set, set git alias >>$logfile
|
||||
if [ "$LC_ALL." == "." ]; then
|
||||
alias git='LANGUAGE=en_US.UTF-8 git' >>$logfile
|
||||
else
|
||||
alias git='LC_ALL=en_US.UTF-8 git' >>$logfile
|
||||
fi
|
||||
#alias >>$logfile
|
||||
fi
|
||||
# get the git remote name
|
||||
remote=$(git remote 2>/dev/null | awk '{print $1}')
|
||||
|
||||
# if remote name set
|
||||
if [ "$remote." != "." ]; then
|
||||
|
||||
echo remote name = $remote >>$logfile
|
||||
|
||||
# get the local and remote package.json versions
|
||||
local_version=$(grep -m1 version package.json | awk -F\" '{print $4}')
|
||||
remote_version=$(curl -s https://raw.githubusercontent.com/MichMich/MagicMirror/master/package.json | grep -m1 version | awk -F\" '{print $4}')
|
||||
|
||||
# only change if they are different
|
||||
if [ "$local_version." != "$remote_version." -o $force == $true -o $test_run == $true ]; then
|
||||
echo upgrading from version $local_version to $remote_version | tee -a $logfile
|
||||
|
||||
# get the latest upgrade
|
||||
echo fetching latest revisions | tee -a $logfile
|
||||
git fetch $remote >/dev/null
|
||||
rc=$?
|
||||
echo git fetch rc=$rc >>$logfile
|
||||
if [ $rc -eq 0 ]; then
|
||||
|
||||
# need to get the current branch
|
||||
current_branch=$(git branch | grep "*" | awk '{print $2}')
|
||||
echo current branch = $current_branch >>$logfile
|
||||
|
||||
git status 2>&1 >>$logfile
|
||||
|
||||
# get the names of the files that are different locally
|
||||
diffs=$(git status 2>&1 | grep modified | awk -F: '{print $2}')
|
||||
|
||||
# split names into an array
|
||||
diffs=($diffs) # split to array $diffs
|
||||
|
||||
# if there are different files (array size greater than zero)
|
||||
if [ ${#diffs[@]} -gt 0 ]; then
|
||||
package_lock=0
|
||||
echo there are "${#diffs[@]}" local files that are different than the master repo | tee -a $logfile
|
||||
echo | tee -a $logfile
|
||||
for file in "${diffs[@]}"
|
||||
do
|
||||
echo "$file" | tee -a $logfile
|
||||
if [ $(echo $file | grep '\-lock.json$' | wc -l) -eq 1 ]; then
|
||||
package_lock=$true
|
||||
fi
|
||||
done
|
||||
echo | tee -a $logfile
|
||||
if [ $package_lock -eq 1 ]; then
|
||||
echo "any *-lock.json files do not need to be saved"
|
||||
fi
|
||||
read -p "do you want to save these files for later (Y/n)?" choice
|
||||
echo save/restore files selection = $choice >> $logfile
|
||||
if [[ $choice =~ ^[Yy]$ ]]; then
|
||||
git_user=$(git config --global --get user.email)
|
||||
if [ "git_user." == "." ]; then
|
||||
git_user_name="-c user.name=upgrade_script"
|
||||
git_user_email="-c user.email=script@upgrade.com"
|
||||
fi
|
||||
git git_user_name git_user_email stash >>$logfile
|
||||
stashed=$true
|
||||
else
|
||||
for file in "${diffs[@]}"
|
||||
do
|
||||
f="$(trim "$file")"
|
||||
echo restoring $f from repo >> $logfile
|
||||
if [ $test_run == $false ]; then
|
||||
git checkout HEAD -- $f | tee -a $logfile
|
||||
else
|
||||
echo skipping restore for $f, doing test run | tee -a $logfile
|
||||
fi
|
||||
done
|
||||
fi
|
||||
else
|
||||
echo no files different from github version >> $logfile
|
||||
fi
|
||||
|
||||
# lets test merge, in memory, no changes to working directory or local repo
|
||||
test_merge_output=$(git merge-tree `git merge-base $current_branch HEAD` HEAD $current_branch | grep "^<<<<<<<\|changed in both")
|
||||
echo "test merge result rc='$test_merge_output' , if empty, no conflicts" >> $logfile
|
||||
|
||||
# if there were no conflicts reported
|
||||
if [ "$test_merge_output." == "." ]; then
|
||||
|
||||
if [ $test_run == $false ]; then
|
||||
# go ahead and merge now
|
||||
echo "executing merge, apply specified" >> $logfile
|
||||
# get the text output of merge
|
||||
merge_output=$(git merge $remote/$current_branch 2>&1)
|
||||
# and its return code
|
||||
merge_result=$?
|
||||
# make any long line readable
|
||||
merge_output=$(echo $merge_output | tr '|' '\n'| sed "s/create/\\${lf}create/g" | sed "s/mode\ change/\\${lf}mode\ change/g")
|
||||
echo -e "merge result rc= $merge_result\n $merge_output">> $logfile
|
||||
else
|
||||
echo "skipping merge, only test run" >> $logfile
|
||||
merge_output=''
|
||||
merge_result=0
|
||||
fi
|
||||
|
||||
# if no merge errors
|
||||
if [ $merge_result == 0 ]; then
|
||||
# some updates applied
|
||||
if [ "$merge_output." != 'Already up to date.' -o $test_run == $true ]; then
|
||||
# update any dependencies for base
|
||||
if [ $doinstalls == $true ]; then
|
||||
# if this is a pi zero
|
||||
echo processor architecture is $arch >> $logfile
|
||||
if [ "$arch" == "armv6l" ]; then
|
||||
# force to look like pi 2
|
||||
echo forcing architecture armv7l >>$logfile
|
||||
forced_arch='--arch=armv7l'
|
||||
fi
|
||||
echo "updating MagicMirror runtime, please wait" | tee -a $logfile
|
||||
npm install $forced_arch 2>&1 | tee -a $logfile
|
||||
done_update=`date +"completed - %a %b %e %H:%M:%S %Z %Y"`
|
||||
echo npm install $done_update on base >> $ logfile
|
||||
fi
|
||||
# process updates for modules after base changed
|
||||
cd modules
|
||||
if [ $justActive == $true ]; then
|
||||
# get the list of ACTIVE modules with package.json files
|
||||
mtype=active
|
||||
modules=$(node ../installers/dumpactivemodules.js)
|
||||
else
|
||||
# get the list of INSTALLED modules with package.json files
|
||||
mtype=installed
|
||||
modules=$(find -maxdepth 2 -name 'package.json' -printf "%h\n" | cut -d'/' -f2 )
|
||||
fi
|
||||
modules=($modules) # split to array $modules
|
||||
|
||||
# if the array has entries in it
|
||||
if [ ${#modules[@]} -gt 0 ]; then
|
||||
echo >> $logfile
|
||||
echo "processing dependency changes for $mtype modules with package.json files" | tee -a $logfile
|
||||
echo
|
||||
for module in "${modules[@]}"
|
||||
do
|
||||
echo "processing for module" $module please wait | tee -a $logfile
|
||||
echo '----------------------------------' | tee -a $logfile
|
||||
# change to that directory
|
||||
cd $module
|
||||
# process its dependencies
|
||||
if [ $doinstalls == $true ]; then
|
||||
npm install $forced_arch 2>&1| tee -a $logfile
|
||||
else
|
||||
echo skipped processing for $module, doing test run | tee -a $logfile
|
||||
fi
|
||||
# return to modules folder
|
||||
cd .. >/dev/null
|
||||
echo "processing complete for module" $module | tee -a $logfile
|
||||
echo
|
||||
done
|
||||
else
|
||||
echo "no modules found needing npm refresh" | tee -a $logfile
|
||||
fi
|
||||
# return to Magic Mirror folder
|
||||
cd .. >/dev/null
|
||||
else
|
||||
echo "no changes detected for modules, skipping " | tee -a $logfile
|
||||
fi
|
||||
else
|
||||
echo there were merge errors | tee -a $logfile
|
||||
echo $merge_output | tee -a %logfile
|
||||
echo you should examine and resolve them | tee -a $logfile
|
||||
echo using the command git log --oneline --decorate | tee -a $logfile
|
||||
git log --oneline --decorate | tee -a $logfile
|
||||
fi
|
||||
else
|
||||
echo "there are merge conflicts to be resolved, no changes have been applied" | tee -a $logfile
|
||||
echo $test_merge_output | tee -a $logfile
|
||||
fi
|
||||
else
|
||||
echo "MagicMirror git fetch failed" | tee -a $logfile
|
||||
fi
|
||||
else
|
||||
echo "local version $local_version already same as master $remote_version" | tee -a $logfile
|
||||
fi
|
||||
else
|
||||
echo "Unable to determine upstream git repository" | tee -a $logfile
|
||||
fi
|
||||
# should be in MagicMirror base
|
||||
cd css
|
||||
# restore custom.css
|
||||
echo "restoring custom.css" | tee -a $logfile
|
||||
cp -p save_custom.css custom.css
|
||||
rm save_custom.css
|
||||
cd - >/dev/null
|
||||
if [ "$lang." != "en_US.UTF-8." ]; then
|
||||
if [ "$save_alias." != "." ]; then
|
||||
echo restoring git alias >>$logfile
|
||||
$save_alias >/dev/null
|
||||
else
|
||||
echo removing git alias >>$logfile
|
||||
unalias git >/dev/null
|
||||
fi
|
||||
fi
|
||||
IFS=$SAVEIFS # Restore IFS
|
||||
|
||||
if [ $stashed == $true ]; then
|
||||
if [ $test_run == $true ]; then
|
||||
echo test run, restoring files stashed | tee -a $logfile
|
||||
git git_user_name git_user_email stash pop >> $logfile
|
||||
else
|
||||
echo we stashed a set of files that appear changed from the latest repo versions. you should review them | tee -a $logfile
|
||||
git stash show --name-only > installers/stashed_files
|
||||
echo see installers/stashed_files for the list
|
||||
echo
|
||||
echo you can use git checkout "stash@{0}" -- filename to extract one file from the stash
|
||||
echo
|
||||
echo or git stash pop to restore them all
|
||||
echo
|
||||
echo WARNING..
|
||||
echo WARNING.. either will overlay the file just installed by the update
|
||||
echo WARNING..
|
||||
fi
|
||||
fi
|
||||
# return to original folder
|
||||
cd - >/dev/null
|
||||
date +"Upgrade ended - %a %b %e %H:%M:%S %Z %Y" >>$logfile
|
||||
else
|
||||
echo It appears MagicMirror has not been installed on this system
|
||||
echo please run the installer, "raspberry.sh" first
|
||||
fi
|
||||
|
@ -1,721 +0,0 @@
|
||||
# MagicMirror² Module Development Documentation
|
||||
|
||||
This document describes the way to develop your own MagicMirror² modules.
|
||||
|
||||
Table of Contents:
|
||||
|
||||
- Module structure
|
||||
- Files
|
||||
|
||||
- The Core module file: modulename.js
|
||||
- Available module instance properties
|
||||
- Subclassable module methods
|
||||
- Module instance methods
|
||||
- Visibility locking
|
||||
|
||||
- The Node Helper: node_helper.js
|
||||
- Available module instance properties
|
||||
- Subclassable module methods
|
||||
- Module instance methods
|
||||
|
||||
- MagicMirror Helper Methods
|
||||
- Module Selection
|
||||
|
||||
- MagicMirror Logger
|
||||
|
||||
---
|
||||
|
||||
|
||||
## General Advice
|
||||
|
||||
As MagicMirror has gained huge popularity, so has the number of available modules. For new users and developers alike, it is very time consuming to navigate around the various repositories in order to find out what exactly a certain modules does, how it looks and what it depends on. Unfortunately, this information is rarely available, nor easily obtained without having to install it first.
|
||||
Therefore **we highly recommend you to include the following information in your README file.**
|
||||
|
||||
- A high quality screenshot of your working module
|
||||
- A short, one sentence, clear description what it does (duh!)
|
||||
- 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.
|
||||
|
||||
## Module structure
|
||||
|
||||
All modules are loaded in the `modules` folder. The default modules are grouped together in the `modules/default` folder. Your module should be placed in a subfolder of `modules`. Note that any file or folder your create in the `modules` folder will be ignored by git, allowing you to upgrade the MagicMirror² without the loss of your files.
|
||||
|
||||
A module can be placed in one single folder. Or multiple modules can be grouped in a subfolder. Note that name of the module must be unique. Even when a module with a similar name is placed in a different folder, they can't be loaded at the same time.
|
||||
|
||||
### 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 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
|
||||
This is the script in which the module will be defined. This script is required in order for the module to be used. In it's most simple form, the core module file must contain:
|
||||
````javascript
|
||||
Module.register("modulename",{});
|
||||
````
|
||||
Of course, the above module would not do anything fancy, so it's good to look at one of the simplest modules: **helloworld**:
|
||||
|
||||
````javascript
|
||||
//helloworld.js:
|
||||
|
||||
Module.register("helloworld",{
|
||||
// Default module config.
|
||||
defaults: {
|
||||
text: "Hello World!"
|
||||
},
|
||||
|
||||
// Override dom generator.
|
||||
getDom: function() {
|
||||
var wrapper = document.createElement("div");
|
||||
wrapper.innerHTML = this.config.text;
|
||||
return wrapper;
|
||||
}
|
||||
});
|
||||
````
|
||||
|
||||
As you can see, the `Module.register()` method takes two arguments: the name of the module and an object with the module properties.
|
||||
|
||||
### Available module instance properties
|
||||
After the module is initialized, the module instance has a few available module properties:
|
||||
|
||||
| Instance Property | Type | Description |
|
||||
|:----------------- |:---- |:----------- |
|
||||
| `this.name` | String | The name of the module. |
|
||||
| `this.identifier` | String | This is a unique identifier for the module instance. |
|
||||
| `this.hidden` | Boolean | This represents if the module is currently hidden (faded away). |
|
||||
| `this.config` | Boolean | The configuration of the module instance as set in the user's `config.js` file. This config will also contain the module's defaults if these properties are not over-written by the user config. |
|
||||
| `this.data` | Object | The data object contain additional metadata about the module instance. (See below) |
|
||||
|
||||
|
||||
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.
|
||||
- `data.header` - The header added to the module.
|
||||
- `data.position` - The position in which the instance will be shown.
|
||||
|
||||
|
||||
#### `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' configuration defaults. Any of the module configuration properties can be accessed using `this.config.propertyName`, but more about that later.
|
||||
|
||||
#### `requiresVersion:`
|
||||
|
||||
*Introduced in version: 2.1.0.*
|
||||
|
||||
A string that defines the minimum version of the MagicMirror framework. If it is set, the system compares the required version with the users version. If the version of the user is out of date, it won't run the module. Make sure to also set this value in the Node helper.
|
||||
|
||||
**Note:** Since this check is introduced in version 2.1.0, this check will not be run in older versions. Keep this in mind if you get issue reports on your module.
|
||||
|
||||
Example:
|
||||
````javascript
|
||||
requiresVersion: "2.1.0",
|
||||
````
|
||||
|
||||
### Subclassable module methods
|
||||
|
||||
#### `init()`
|
||||
This method is called when a module gets instantiated. In most cases you do not need to subclass this method.
|
||||
|
||||
#### `loaded(callback)`
|
||||
|
||||
*Introduced in version: 2.1.1.*
|
||||
|
||||
This method is called when a module is loaded. Subsequent modules in the config are not yet loaded. The `callback` function MUST be called when the module is done loading. In most cases you do not need to subclass this method.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
loaded: function(callback) {
|
||||
this.finishLoading();
|
||||
Log.log(this.name + ' is loaded!');
|
||||
callback();
|
||||
}
|
||||
````
|
||||
|
||||
#### `start()`
|
||||
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
|
||||
start: function() {
|
||||
this.mySpecialProperty = "So much wow!";
|
||||
Log.log(this.name + ' is started!');
|
||||
}
|
||||
````
|
||||
|
||||
#### `getScripts()`
|
||||
**Should return: Array**
|
||||
|
||||
The getScripts method is called to request any additional scripts that need to be loaded. This method should therefore return an array with strings. If you want to return a full path to a file in the module folder, use the `this.file('filename.js')` method. In all cases the loader will only load a file once. It even checks if the file is available in the default vendor folder.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
getScripts: function() {
|
||||
return [
|
||||
'script.js', // will try to load it from the vendor folder, otherwise it will load is from the module folder.
|
||||
'moment.js', // this file is available in the vendor folder, so it doesn't need to be available in the module folder.
|
||||
this.file('anotherfile.js'), // this file will be loaded straight from the module folder.
|
||||
'https://code.jquery.com/jquery-2.2.3.min.js', // this file will be loaded from the jquery 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.
|
||||
|
||||
|
||||
#### `getStyles()`
|
||||
**Should return: Array**
|
||||
|
||||
The getStyles method is called to request any additional stylesheets that need to be loaded. This method should therefore return an array with strings. If you want to return a full path to a file in the module folder, use the `this.file('filename.css')` method. In all cases the loader will only load a file once. It even checks if the file is available in the default vendor folder.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
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 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.
|
||||
|
||||
#### `getTranslations()`
|
||||
**Should return: Dictionary**
|
||||
|
||||
The getTranslations method is called to request translation files that need to be loaded. This method should therefore return a dictionary with the files to load, identified by the country's short name.
|
||||
|
||||
If the module does not have any module specific translations, the function can just be omitted or return `false`.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
getTranslations: function() {
|
||||
return {
|
||||
en: "translations/en.json",
|
||||
de: "translations/de.json"
|
||||
}
|
||||
}
|
||||
|
||||
````
|
||||
|
||||
#### `getDom()`
|
||||
**Should return:** Dom Object
|
||||
|
||||
Whenever the MagicMirror needs to update the information on screen (because it starts, or because your module asked a refresh using `this.updateDom()`), the system calls the getDom method. This method should therefore return a dom object.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
getDom: function() {
|
||||
var wrapper = document.createElement("div");
|
||||
wrapper.innerHTML = 'Hello world!';
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
````
|
||||
|
||||
#### `getHeader()`
|
||||
**Should return:** String
|
||||
|
||||
Whenever the MagicMirror needs to update the information on screen (because it starts, or because your module asked a refresh using `this.updateDom()`), the system calls the getHeader method to retrieve the module's header. This method should therefor return a string. If this method is not subclassed, this function will return the user's configured header.
|
||||
|
||||
If you want to use the original user's configured header, reference `this.data.header`.
|
||||
|
||||
**NOTE:** If the user did not configure a default header, no header will be displayed and thus this method will not be called.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
getHeader: function() {
|
||||
return this.data.header + ' Foo Bar';
|
||||
}
|
||||
|
||||
````
|
||||
|
||||
#### `notificationReceived(notification, payload, sender)`
|
||||
|
||||
That MagicMirror core has the ability to send notifications to modules. Or even better: the modules have the possibility to send notifications to other modules. When this module is called, it has 3 arguments:
|
||||
|
||||
- `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 notification is the core system.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
notificationReceived: function(notification, payload, sender) {
|
||||
if (sender) {
|
||||
Log.log(this.name + " received a module notification: " + notification + " from sender: " + sender.name);
|
||||
} else {
|
||||
Log.log(this.name + " received a system notification: " + notification);
|
||||
}
|
||||
}
|
||||
````
|
||||
|
||||
**Note:** the system sends three notifications when starting up. These notifications could come in handy!
|
||||
|
||||
|
||||
- `ALL_MODULES_STARTED` - All modules are started. You can now send notifications to other modules.
|
||||
- `DOM_OBJECTS_CREATED` - All dom objects are created. The system is now ready to perform visual changes.
|
||||
- `MODULE_DOM_CREATED` - This module's dom has been fully loaded. You can now access your module's dom objects.
|
||||
|
||||
|
||||
#### `socketNotificationReceived: function(notification, payload)`
|
||||
When using a node_helper, the node helper can send your module notifications. When this module is called, it has 2 arguments:
|
||||
|
||||
- `notification` - String - The notification identifier.
|
||||
- `payload` - AnyType - The payload of a notification.
|
||||
|
||||
**Note 1:** When a node helper sends a notification, all modules of that module type receive the same notifications. <br>
|
||||
**Note 2:** The socket connection is established as soon as the module sends its first message using [sendSocketNotification](#thissendsocketnotificationnotification-payload).
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
socketNotificationReceived: function(notification, payload) {
|
||||
Log.log(this.name + " received a socket notification: " + notification + " - Payload: " + payload);
|
||||
},
|
||||
````
|
||||
|
||||
#### `suspend()`
|
||||
When a module is hidden (using the `module.hide()` method), the `suspend()` method will be called. By subclassing this method you can perform tasks like halting the update timers.
|
||||
|
||||
#### `resume()`
|
||||
When a module is requested to be shown (using the `module.show()` method), the `resume()` method will be called. By subclassing this method you can perform tasks restarting the update timers.
|
||||
|
||||
|
||||
### Module instance methods
|
||||
|
||||
Each module instance has some handy methods which can be helpful building your module.
|
||||
|
||||
|
||||
#### `this.file(filename)`
|
||||
***filename* String** - The name of the file you want to create the path for.<br>
|
||||
**Returns String**
|
||||
|
||||
If you want to create a path to a file in your module folder, use the `file()` method. It returns the path to the filename given as the attribute. Is method comes in handy when configuring the [getScripts](#getscripts) and [getStyles](#getstyles) methods.
|
||||
|
||||
#### `this.updateDom(speed)`
|
||||
***speed* Number** - Optional. Animation speed in milliseconds.<br>
|
||||
|
||||
Whenever your module need to be updated, call the `updateDom(speed)` method. It requests the MagicMirror core to update its dom object. If you define the speed, the content update will be animated, but only if the content will really change.
|
||||
|
||||
As an example: the clock modules calls this method every second:
|
||||
|
||||
````javascript
|
||||
...
|
||||
start: function() {
|
||||
var self = this;
|
||||
setInterval(function() {
|
||||
self.updateDom(); // no speed defined, so it updates instantly.
|
||||
}, 1000); //perform every 1000 milliseconds.
|
||||
},
|
||||
...
|
||||
````
|
||||
|
||||
#### `this.sendNotification(notification, payload)`
|
||||
***notification* String** - The notification identifier.<br>
|
||||
***payload* AnyType** - Optional. A notification payload.<br>
|
||||
|
||||
If you want to send a notification to all other modules, use the `sendNotification(notification, payload)`. All other modules will receive the message via the [notificationReceived](#notificationreceivednotification-payload-sender) method. In that case, the sender is automatically set to the instance calling the sendNotification method.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
this.sendNotification('MYMODULE_READY_FOR_ACTION', {foo:bar});
|
||||
````
|
||||
|
||||
#### `this.sendSocketNotification(notification, payload)`
|
||||
***notification* String** - The notification identifier.<br>
|
||||
***payload* AnyType** - Optional. A notification payload.<br>
|
||||
|
||||
If you want to send a notification to the node_helper, use the `sendSocketNotification(notification, payload)`. Only the node_helper of this module will receive the socket notification.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
this.sendSocketNotification('SET_CONFIG', this.config);
|
||||
````
|
||||
|
||||
#### `this.hide(speed, callback, options)`
|
||||
***speed* Number** - Optional (Required when setting callback or options), The speed of the hide animation in milliseconds.
|
||||
***callback* Function** - Optional, The callback after the hide animation is finished.
|
||||
***options* Function** - Optional, Object with additional options for the hide action (see below). (*Introduced in version: 2.1.0.*)
|
||||
|
||||
To hide a module, you can call the `hide(speed, callback)` method. You can call the hide method on the module instance itself using `this.hide()`, but of course you can also hide another module using `anOtherModule.hide()`.
|
||||
|
||||
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 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).
|
||||
|
||||
|
||||
#### `this.show(speed, callback, options)`
|
||||
***speed* Number** - Optional (Required when setting callback or options), The speed of the show animation in milliseconds.
|
||||
***callback* Function** - Optional, The callback after the show animation is finished.
|
||||
***options* Function** - Optional, Object with additional options for the show action (see below). (*Introduced in version: 2.1.0.*)
|
||||
|
||||
To show a module, you can call the `show(speed, callback)` method. You can call the show method on the module instance itself using `this.show()`, but of course you can also show another module using `anOtherModule.show()`.
|
||||
|
||||
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. See *visibility locking* below.
|
||||
- `force` - Boolean - When setting the force tag to `true`, the locking mechanism will be overwritten. Use this option with caution. It's considered best practice to let the usage of the force option be use- configurable. See *visibility locking* below.
|
||||
|
||||
**Note 1:** If the show animation is canceled, for instance because the hide method is called before the show animation was finished, the callback will not be called.<br>
|
||||
**Note 2:** If the show animation is hijacked (an other method calls show on the same module), the callback will not be called.<br>
|
||||
**Note 3:** If the dom is not yet created, the show method won't work. Wait for the `DOM_OBJECTS_CREATED` [notification](#notificationreceivednotification-payload-sender).
|
||||
|
||||
#### Visibility locking
|
||||
|
||||
(*Introduced in version: 2.1.0.*)
|
||||
|
||||
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
|
||||
moduleA.hide(0, {lockString: "module_b_identifier"});
|
||||
````
|
||||
Module A is now hidden, and has an lock array with the following strings:
|
||||
````javascript
|
||||
moduleA.lockStrings == ["module_b_identifier"]
|
||||
moduleA.hidden == true
|
||||
````
|
||||
**Module C asks module A to hide:**
|
||||
````javascript
|
||||
moduleA.hide(0, {lockString: "module_c_identifier"});
|
||||
````
|
||||
Module A is now hidden, and has an lock array with the following strings:
|
||||
````javascript
|
||||
moduleA.lockStrings == ["module_b_identifier", "module_c_identifier"]
|
||||
moduleA.hidden == true
|
||||
````
|
||||
**Module B asks module A to show:**
|
||||
````javascript
|
||||
moduleA.show(0, {lockString: "module_b_identifier"});
|
||||
````
|
||||
The lockString will be removed from moduleA’s locks array, but since there still is an other lock string available, the module remains hidden:
|
||||
````javascript
|
||||
moduleA.lockStrings == ["module_c_identifier"]
|
||||
moduleA.hidden == true
|
||||
````
|
||||
**Module C asks module A to show:**
|
||||
````javascript
|
||||
moduleA.show(0, {lockString: "module_c_identifier"});
|
||||
````
|
||||
The lockString will be removed from moduleA’s locks array, and since this will result in an empty lock array, the module will be visible:
|
||||
````javascript
|
||||
moduleA.lockStrings == []
|
||||
moduleA.hidden == false
|
||||
````
|
||||
|
||||
**Note:** The locking mechanism can be overwritten by using the force tag:
|
||||
````javascript
|
||||
moduleA.show(0, {force: true});
|
||||
````
|
||||
This will reset the lockstring array, and will show the module.
|
||||
````javascript
|
||||
moduleA.lockStrings == []
|
||||
moduleA.hidden == false
|
||||
````
|
||||
|
||||
Use this `force` method with caution. See `show()` method for more information.
|
||||
|
||||
|
||||
|
||||
#### `this.translate(identifier)`
|
||||
***identifier* String** - Identifier of the string that should be translated.
|
||||
|
||||
The Magic Mirror contains a convenience wrapper for `l18n`. You can use this to automatically serve different translations for your modules based on the user's `language` configuration.
|
||||
|
||||
If no translation is found, a fallback will be used. The fallback sequence is as follows:
|
||||
- 1. Translation as defined in module translation file of the user's preferred language.
|
||||
- 2. Translation as defined in core translation file of the user's preferred language.
|
||||
- 3. Translation as defined in module translation file of the fallback language (the first defined module translation file).
|
||||
- 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 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
|
||||
this.translate("INFO") //Will return a translated string for the identifier INFO
|
||||
````
|
||||
|
||||
**Example json file:**
|
||||
````javascript
|
||||
{
|
||||
"INFO": "Really important information!"
|
||||
}
|
||||
````
|
||||
|
||||
**Note:** although comments are officially not supported in JSON files, MagicMirror allows it by stripping the comments before parsing the JSON file. Comments in translation files could help other translators.
|
||||
|
||||
##### `this.translate(identifier, variables)`
|
||||
***identifier* String** - Identifier of the string that should be translated.
|
||||
***variables* Object** - Object of variables to be used in translation.
|
||||
|
||||
This improved and backwards compatible way to handle translations behaves like the normal translation function and follows the rules described above. It's recommended to use this new format for translating everywhere. It allows translator to change the word order in the sentence to be translated.
|
||||
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
var timeUntilEnd = moment(event.endDate, "x").fromNow(true);
|
||||
this.translate("RUNNING", { "timeUntilEnd": timeUntilEnd) }); // Will return a translated string for the identifier RUNNING, replacing `{timeUntilEnd}` with the contents of the variable `timeUntilEnd` in the order that translator intended.
|
||||
````
|
||||
|
||||
**Example English .json file:**
|
||||
````javascript
|
||||
{
|
||||
"RUNNING": "Ends in {timeUntilEnd}",
|
||||
}
|
||||
````
|
||||
|
||||
**Example Finnish .json file:**
|
||||
````javascript
|
||||
{
|
||||
"RUNNING": "Päättyy {timeUntilEnd} päästä",
|
||||
}
|
||||
````
|
||||
|
||||
**Note:** The *variables* Object has an special case called `fallback`. It's used to support old translations in translation files that do not have the variables in them. If you are upgrading an old module that had translations that did not support the word order, it is recommended to have the fallback layout.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
var timeUntilEnd = moment(event.endDate, "x").fromNow(true);
|
||||
this.translate("RUNNING", {
|
||||
"fallback": this.translate("RUNNING") + " {timeUntilEnd}"
|
||||
"timeUntilEnd": timeUntilEnd
|
||||
)}); // 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:**
|
||||
````javascript
|
||||
{
|
||||
"RUNNING": "Slutar",
|
||||
}
|
||||
````
|
||||
In this case the `translate`-function will not find any variables in the translation, will look for `fallback` variable and use that if possible to create the translation.
|
||||
|
||||
## The Node Helper: node_helper.js
|
||||
|
||||
The node helper is a Node.js script that is able to do some backend task to support your module. For every module type, only one node helper instance will be created. For example: if your MagicMirror uses two calendar modules, there will be only one calendar node helper instantiated.
|
||||
|
||||
**Note:** Because there is only one node helper per module type, there is no default config available within your module. It's your task to send the desired config from your module to your node helper.
|
||||
|
||||
In it's most simple form, the node_helper.js file must contain:
|
||||
|
||||
````javascript
|
||||
var NodeHelper = require("node_helper");
|
||||
module.exports = NodeHelper.create({});
|
||||
````
|
||||
|
||||
Of course, the above helper would not do anything useful. So with the information above, you should be able to make it a bit more sophisticated.
|
||||
|
||||
### Available module instance properties
|
||||
|
||||
#### `this.name`
|
||||
**String**
|
||||
|
||||
The name of the module
|
||||
|
||||
#### `this.path`
|
||||
**String**
|
||||
|
||||
The path of the module
|
||||
|
||||
#### `this.expressApp`
|
||||
**Express App Instance**
|
||||
|
||||
This is a link to the express instance. It will allow you to define extra routes.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
start: function() {
|
||||
this.expressApp.get('/foobar', function (req, res) {
|
||||
res.send('GET request to /foobar');
|
||||
});
|
||||
}
|
||||
````
|
||||
|
||||
**Note:** By default, a public path to your module's public folder will be created:
|
||||
````javascript
|
||||
this.expressApp.use("/" + this.name, express.static(this.path + "/public"));
|
||||
````
|
||||
|
||||
#### `this.io`
|
||||
**Socket IO Instance**
|
||||
|
||||
This is a link to the IO instance. It will allow you to do some Socket.IO magic. In most cases you won't need this, since the Node Helper has a few convenience methods to make this simple.
|
||||
|
||||
|
||||
#### `requiresVersion:`
|
||||
*Introduced in version: 2.1.0.*
|
||||
|
||||
A string that defines the minimum version of the MagicMirror framework. If it is set, the system compares the required version with the users version. If the version of the user is out of date, it won't run the module.
|
||||
|
||||
**Note:** Since this check is introduced in version 2.1.0, this check will not be run in older versions. Keep this in mind if you get issue reports on your module.
|
||||
|
||||
Example:
|
||||
````javascript
|
||||
requiresVersion: "2.1.0",
|
||||
````
|
||||
|
||||
### Subclassable module methods
|
||||
|
||||
#### `init()`
|
||||
This method is called when a node helper gets instantiated. In most cases you do not need to subclass this method.
|
||||
|
||||
#### `start()`
|
||||
This method is called when all node helpers are loaded and the system is ready to boot up. The start method is a perfect place to define any additional module properties:
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
start: function() {
|
||||
this.mySpecialProperty = "So much wow!";
|
||||
Log.log(this.name + ' is started!');
|
||||
}
|
||||
````
|
||||
|
||||
#### `stop()`
|
||||
This method is called when the MagicMirror server receives a `SIGINT` command and is shutting down. This method should include any commands needed to close any open connections, stop any sub-processes and gracefully exit the module.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
stop: function() {
|
||||
console.log("Shutting down MyModule");
|
||||
this.connection.close();
|
||||
}
|
||||
````
|
||||
|
||||
#### `socketNotificationReceived: function(notification, payload)`
|
||||
With this method, your node helper can receive notifications from your modules. When this method is called, it has 2 arguments:
|
||||
|
||||
- `notification` - String - The notification identifier.
|
||||
- `payload` - AnyType - The payload of a notification.
|
||||
|
||||
**Note:** The socket connection is established as soon as the module sends its first message using [sendSocketNotification](thissendsocketnotificationnotification-payload).
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
socketNotificationReceived: function(notification, payload) {
|
||||
Log.log(this.name + " received a socket notification: " + notification + " - Payload: " + payload);
|
||||
},
|
||||
````
|
||||
|
||||
### Module instance methods
|
||||
|
||||
Each node helper has some handy methods which can be helpful building your module.
|
||||
|
||||
#### `this.sendSocketNotification(notification, payload)`
|
||||
***notification* String** - The notification identifier.<br>
|
||||
***payload* AnyType** - Optional. A notification payload.<br>
|
||||
|
||||
If you want to send a notification to all your modules, use the `sendSocketNotification(notification, payload)`. Only the module of your module type will receive the socket notification.
|
||||
|
||||
**Note:** Since all instances of your module will receive the notifications, it's your task to make sure the right module responds to your messages.
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
this.sendSocketNotification('SET_CONFIG', this.config);
|
||||
````
|
||||
|
||||
## MagicMirror Helper Methods
|
||||
|
||||
The core Magic Mirror object: `MM` has some handy method that will help you in controlling your and other modules. Most of the `MM` methods are available via convenience methods on the Module instance.
|
||||
|
||||
### Module selection
|
||||
The only additional method available for your module, is the feature to retrieve references to other modules. This can be used to hide and show other modules.
|
||||
|
||||
#### `MM.getModules()`
|
||||
**Returns Array** - An array with module instances.<br>
|
||||
|
||||
To make a selection of all currently loaded module instances, run the `MM.getModules()` method. It will return an array with all currently loaded module instances. The returned array has a lot of filtering methods. See below for more info.
|
||||
|
||||
**Note:** This method returns an empty array if not all modules are started yet. Wait for the `ALL_MODULES_STARTED` [notification](#notificationreceivednotification-payload-sender).
|
||||
|
||||
|
||||
##### `.withClass(classnames)`
|
||||
***classnames* String or Array** - The class names on which you want to filter.
|
||||
**Returns Array** - An array with module instances.<br>
|
||||
|
||||
If you want to make a selection based on one or more class names, use the withClass method on a result of the `MM.getModules()` method. The argument of the `withClass(classname)` method can be an array, or space separated string.
|
||||
|
||||
**Examples:**
|
||||
````javascript
|
||||
var modules = MM.getModules().withClass('classname');
|
||||
var modules = MM.getModules().withClass('classname1 classname2');
|
||||
var modules = MM.getModules().withClass(['classname1','classname2']);
|
||||
````
|
||||
|
||||
##### `.exceptWithClass(classnames)`
|
||||
***classnames* String or Array** - The class names of the modules you want to remove from the results.
|
||||
**Returns Array** - An array with module instances.<br>
|
||||
|
||||
If you to remove some modules from a selection based on a classname, use the exceptWithClass method on a result of the `MM.getModules()` method. The argument of the `exceptWithClass(classname)` method can be an array, or space separated string.
|
||||
|
||||
**Examples:**
|
||||
````javascript
|
||||
var modules = MM.getModules().exceptWithClass('classname');
|
||||
var modules = MM.getModules().exceptWithClass('classname1 classname2');
|
||||
var modules = MM.getModules().exceptWithClass(['classname1','classname2']);
|
||||
````
|
||||
|
||||
##### `.exceptModule(module)`
|
||||
***module* Module Object** - The reference to a module you want to remove from the results.
|
||||
**Returns Array** - An array with module instances.<br>
|
||||
|
||||
If you to remove a specific module instance from a selection based on a classname, use the exceptWithClass method on a result of the `MM.getModules()` method. This can be helpful if you want to select all module instances except the instance of your module.
|
||||
|
||||
**Examples:**
|
||||
````javascript
|
||||
var modules = MM.getModules().exceptModule(this);
|
||||
````
|
||||
|
||||
Of course, you can combine all of the above filters:
|
||||
|
||||
**Example:**
|
||||
````javascript
|
||||
var modules = MM.getModules().withClass('classname1').exceptwithClass('classname2').exceptModule(aModule);
|
||||
````
|
||||
|
||||
##### `.enumerate(callback)`
|
||||
***callback* Function(module)** - The callback run on every instance.
|
||||
|
||||
If you want to perform an action on all selected modules, you can use the `enumerate` function:
|
||||
|
||||
````javascript
|
||||
MM.getModules().enumerate(function(module) {
|
||||
Log.log(module.name);
|
||||
});
|
||||
````
|
||||
|
||||
**Example:**
|
||||
To hide all modules except the your module instance, you could write something like:
|
||||
````javascript
|
||||
Module.register("modulename",{
|
||||
//...
|
||||
notificationReceived: function(notification, payload, sender) {
|
||||
if (notification === 'DOM_OBJECTS_CREATED') {
|
||||
MM.getModules().exceptModule(this).enumerate(function(module) {
|
||||
module.hide(1000, function() {
|
||||
//Module hidden.
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
//...
|
||||
});
|
||||
````
|
||||
|
||||
## MagicMirror Logger
|
||||
|
||||
The Magic Mirror contains a convenience wrapper for logging. Currently, this logger is a simple proxy to the original `console.log` methods. But it might get additional features in the future. The Loggers is currently only available in the core module file (not in the node_helper).
|
||||
|
||||
**Examples:**
|
||||
````javascript
|
||||
Log.info('error');
|
||||
Log.log('log');
|
||||
Log.error('info');
|
||||
````
|
@ -1,65 +1,4 @@
|
||||
# Module: Alert
|
||||
The alert module is one of the default modules of the MagicMirror. This module displays notifications from other modules.
|
||||
|
||||
## Usage
|
||||
To use this module, add it to the modules array in the config/config.js file:
|
||||
|
||||
```
|
||||
modules: [
|
||||
{
|
||||
module: "alert",
|
||||
config: {
|
||||
// The config property is optional.
|
||||
// See 'Configuration options' for more information.
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Configuration options
|
||||
|
||||
The following properties can be configured:
|
||||
|
||||
|
||||
| Option | Description
|
||||
| ----------------- | -----------
|
||||
| `effect` | The animation effect to use for notifications. <br><br> **Possible values:** `scale` `slide` `genie` `jelly` `flip` `exploader` `bouncyflip` <br> **Default value:** `slide`
|
||||
| `alert_effect` | The animation effect to use for alerts. <br><br> **Possible values:** `scale` `slide` `genie` `jelly` `flip` `exploader` `bouncyflip` <br> **Default value:** `jelly`
|
||||
| `display_time` | Time a notification is displayed in milliseconds. <br><br> **Possible values:** `int` <br> **Default value:** `3500`
|
||||
| `position` | Position where the notifications should be displayed. <br><br> **Possible values:** `left` `center` `right` <br> **Default value:** `center`
|
||||
| `welcome_message` | Message shown at startup. <br><br> **Possible values:** `string` `false` <br> **Default value:** `false` (no message at startup)
|
||||
|
||||
|
||||
## Developer notes
|
||||
For notifications use:
|
||||
|
||||
```
|
||||
self.sendNotification("SHOW_ALERT", {type: "notification"});
|
||||
```
|
||||
For alerts use:
|
||||
|
||||
```
|
||||
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`
|
||||
| `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
|
||||
| Option | Description
|
||||
| ----------------------------------------------- | -----------
|
||||
| `title` | The title of the alert. <br><br> **Possible values:** `text` or `html`
|
||||
| `message` | The message of the alert. <br><br> **Possible values:** `text` or `html`
|
||||
| `imageUrl` (optional) | Image to show in the alert <br><br> **Possible values:** `url` `path` <br> **Default value:** `none`
|
||||
| `imageFA` (optional) | Font Awesome icon to show in the alert <br><br> **Possible values:** See [Font Awsome](http://fontawesome.io/icons/) website. <br> **Default value:** `none`
|
||||
| `imageHeight` (optional even with imageUrl set) | Height of the image <br><br> **Possible values:** `intpx` <br> **Default value:** `80px`
|
||||
| `timer` (optional) | How long the alert should stay visible in ms. <br> **Important:** If you do not use the `timer`, it is your duty to hide the alert by using `self.sendNotification("HIDE_ALERT");`! <br><br>**Possible values:** `int` `float` <br> **Default value:** `none`
|
||||
|
||||
## Open Source Licenses
|
||||
### [NotificationStyles](https://github.com/codrops/NotificationStyles)
|
||||
See [tympanus.net](http://tympanus.net/codrops/licensing/) for license.
|
||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/alert.html).
|
@ -2,107 +2,4 @@
|
||||
The `calendar` module is one of the default modules of the MagicMirror.
|
||||
This module displays events from a public .ical calendar. It can combine multiple calendars.
|
||||
|
||||
## Using the module
|
||||
|
||||
To use this module, add it to the modules array in the `config/config.js` file:
|
||||
````javascript
|
||||
modules: [
|
||||
{
|
||||
module: "calendar",
|
||||
position: "top_left", // This can be any of the regions. Best results in left or right regions.
|
||||
config: {
|
||||
// The config property is optional.
|
||||
// If no config is set, an example calendar is shown.
|
||||
// See 'Configuration options' for more information.
|
||||
}
|
||||
}
|
||||
]
|
||||
````
|
||||
|
||||
## Configuration options
|
||||
|
||||
The following properties can be configured:
|
||||
|
||||
|
||||
| Option | Description
|
||||
| ---------------------------- | -----------
|
||||
| `maximumEntries` | The maximum number of events shown. / **Possible values:** `0` - `100` <br> **Default value:** `10`
|
||||
| `maximumNumberOfDays` | The maximum number of days in the future. <br><br> **Default value:** `365`
|
||||
| `displaySymbol` | Display a symbol in front of an entry. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `defaultSymbol` | The default symbol. <br><br> **Possible values:** See [Font Awsome](http://fontawesome.io/icons/) website. <br> **Default value:** `calendar`
|
||||
| `showLocation` | Whether to show event locations. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||
| `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`
|
||||
| `fadePoint` | Where to start fade? <br><br> **Possible values:** `0` (top of the list) - `1` (bottom of list) <br> **Default value:** `0.25`
|
||||
| `tableClass` | Name of the classes issued from `main.css`. <br><br> **Possible values:** xsmall, small, medium, large, xlarge. <br> **Default value:** _small._
|
||||
| `calendars` | The list of calendars. <br><br> **Possible values:** An array, see _calendar configuration_ below. <br> **Default value:** _An example calendar._
|
||||
| `titleReplace` | An object of textual replacements applied to the tile of the event. This allow to remove or replace certains words in the title. <br><br> **Example:** `{'Birthday of ' : '', 'foo':'bar'}` <br> **Default value:** `{ "De verjaardag van ": "", "'s birthday": "" }`
|
||||
| `displayRepeatingCountTitle` | Show count title for yearly repeating events (e.g. "X. Birthday", "X. Anniversary") <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||
| `dateFormat` | Format to use for the date of events (when using absolute dates) <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `MMM Do` (e.g. Jan 18th)
|
||||
| `dateEndFormat` | Format to use for the end time of events <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `HH:mm` (e.g. 16:30)
|
||||
| `showEnd` | Show end time of events <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `fullDayEventDateFormat` | Format to use for the date of full day events (when using absolute dates) <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `MMM Do` (e.g. Jan 18th)
|
||||
| `timeFormat` | Display event times as absolute dates, or relative time, or using absolute date headers with times for each event next to it <br><br> **Possible values:** `absolute` or `relative` or `dateheaders` <br> **Default value:** `relative`
|
||||
| `showEnd` | Display the end of a date as well <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `getRelative` | How much time (in hours) should be left until calendar events start getting relative? <br><br> **Possible values:** `0` (events stay absolute) - `48` (48 hours before the event starts) <br> **Default value:** `6`
|
||||
| `urgency` | When using a timeFormat of `absolute`, the `urgency` setting allows you to display events within a specific time frame as `relative`. This allows events within a certain time frame to be displayed as relative (in xx days) while others are displayed as absolute dates <br><br> **Possible values:** a positive integer representing the number of days for which you want a relative date, for example `7` (for 7 days) <br><br> **Default value:** `7`
|
||||
| `broadcastEvents` | If this property is set to true, the calendar will broadcast all the events to all other modules with the notification message: `CALENDAR_EVENTS`. The event objects are stored in an array and contain the following fields: `title`, `startDate`, `endDate`, `fullDayEvent`, `location` and `geo`. <br><br> **Possible values:** `true`, `false` <br><br> **Default value:** `true`
|
||||
| `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:** `[]`
|
||||
| `broadcastPastEvents` | If this is set to true, events from the past `maximumNumberOfDays` will be included in event broadcasts <br> **Default value:** `false`
|
||||
| `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 <br> **Default value:** `true`
|
||||
| `nextDaysRelative ` | If this is set to true, the appointments of today and tomorrow are displayed relatively, even if the timeformat is set to absolute. <br> **Default value:** `false`
|
||||
|
||||
### Calendar configuration
|
||||
|
||||
The `calendars` property contains an array of the configured calendars.
|
||||
The `colored` property gives the option for an individual color for each calendar.
|
||||
The `coloredSymbolOnly` property will apply color to the symbol only, not the whole line. This is only applicable when `colored` is also enabled.
|
||||
|
||||
#### Default value:
|
||||
````javascript
|
||||
config: {
|
||||
colored: false,
|
||||
coloredSymbolOnly: false,
|
||||
calendars: [
|
||||
{
|
||||
url: 'http://www.calendarlabs.com/templates/ical/US-Holidays.ics',
|
||||
symbol: 'calendar',
|
||||
auth: {
|
||||
user: 'username',
|
||||
pass: 'superstrongpassword',
|
||||
method: 'basic'
|
||||
}
|
||||
},
|
||||
],
|
||||
}
|
||||
````
|
||||
|
||||
#### Calendar configuration options:
|
||||
| Option | Description
|
||||
| --------------------- | -----------
|
||||
| `url` | The url of the calendar .ical. This property is required. <br><br> **Possible values:** Any public accessble .ical calendar.
|
||||
| `symbol` | The symbol to show in front of an event. This property is optional. <br><br> **Possible values:** See [Font Awesome](http://fontawesome.io/icons/) website. To have multiple symbols you can define them in an array e.g. `["calendar", "plane"]`
|
||||
| `color` | The font color of an event from this calendar. This property should be set if the config is set to colored: true. <br><br> **Possible values:** HEX, RGB or RGBA values (#efefef, rgb(242,242,242), rgba(242,242,242,0.5)).
|
||||
| `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.
|
||||
| `timeClass` | Add a class to the time's cell.
|
||||
| `broadcastPastEvents` | Whether to include past events from this calendar. Overrides global setting
|
||||
|
||||
|
||||
#### Calendar authentication options:
|
||||
| Option | Description
|
||||
| --------------------- | -----------
|
||||
| `user` | The username for HTTP authentication.
|
||||
| `pass` | The password for HTTP authentication. (If you use Bearer authentication, this should be your BearerToken.)
|
||||
| `method` | Which authentication method should be used. HTTP Basic, Digest and Bearer authentication methods are supported. Basic authentication is used by default if this option is omitted. **Possible values:** `digest`, `basic`, `bearer` **Default value:** `basic`
|
||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/calendar.html).
|
@ -2,56 +2,4 @@
|
||||
The `clock` module is one of the default modules of the MagicMirror.
|
||||
This module displays the current date and time. The information will be updated realtime.
|
||||
|
||||
## Screenshot
|
||||
|
||||
- Current time
|
||||

|
||||
|
||||
## Using the module
|
||||
|
||||
To use this module, add it to the modules array in the `config/config.js` file:
|
||||
````javascript
|
||||
modules: [
|
||||
{
|
||||
module: "clock",
|
||||
position: "top_left", // This can be any of the regions.
|
||||
config: {
|
||||
// The config property is optional.
|
||||
// See 'Configuration options' for more information.
|
||||
}
|
||||
}
|
||||
]
|
||||
````
|
||||
|
||||
## Configuration options
|
||||
|
||||
The following properties can be configured:
|
||||
|
||||
| Option | Description
|
||||
| ----------------- | -----------
|
||||
| `timeFormat` | Use 12 or 24 hour format. <br><br> **Possible values:** `12` or `24` <br> **Default value:** uses value of _config.timeFormat_
|
||||
| `displaySeconds` | Display seconds. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `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`
|
||||
| `clockBold` | Remove the colon and bold the minutes to make a more modern look. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||
| `showDate` | Turn off or on the Date section. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `showWeek` | Turn off or on the Week section. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||
| `dateFormat` | Configure the date format as you like. <br><br> **Possible values:** [Docs](http://momentjs.com/docs/#/displaying/format/) <br> **Default value:** `"dddd, LL"`
|
||||
| `displayType` | Display a digital clock, analog clock, or both together. <br><br> **Possible values:** `digital`, `analog`, or `both` <br> **Default value:** `digital`
|
||||
| `analogSize` | **Specific to the analog clock.** Defines how large the analog display is. <br><br> **Possible values:** A positive number of pixels` <br> **Default value:** `200px`
|
||||
| `analogFace` | **Specific to the analog clock.** Specifies which clock face to use. <br><br> **Possible values:** `simple` for a simple border, `none` for no face or border, or `face-###` (where ### is currently a value between 001 and 012, inclusive) <br> **Default value:** `simple`
|
||||
| `secondsColor` | **Specific to the analog clock.** Specifies what color to make the 'seconds' hand. <br><br> **Possible values:** `any HTML RGB Color` <br> **Default value:** `#888888`
|
||||
| `analogPlacement` | **Specific to the analog clock. _(requires displayType set to `'both'`)_** Specifies where the analog clock is in relation to the digital clock <br><br> **Possible values:** `top`, `right`, `bottom`, or `left` <br> **Default value:** `bottom`
|
||||
| `analogShowDate` | **Specific to the analog clock.** If the clock is used as a separate module and set to analog only, this configures whether a date is also displayed with the clock. <br><br> **Possible values:** `false`, `top`, or `bottom` <br> **Default value:** `top`
|
||||
| `timezone` | Specific a timezone to show clock. <br><br> **Possible examples values:** `America/New_York`, `America/Santiago`, `Etc/GMT+10` <br> **Default value:** `none`. See more informations about configuration value [here](https://momentjs.com/timezone/docs/#/data-formats/packed-format/)
|
||||
|
||||
## Notifications
|
||||
|
||||
The clock makes use of the built-in [Notification Mechanism](https://github.com/michMich/MagicMirror/wiki/notifications) to relay notifications to all modules.
|
||||
|
||||
Current notifications are:
|
||||
|
||||
| Notification | Description
|
||||
| ----------------- | -----------
|
||||
| `CLOCK_SECOND` | A second has elapsed. <br> *Parameter*: second value
|
||||
| `CLOCK_MINUTE` | A minute has elapsed <br> *Parameter*: minute value
|
||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/clock.html).
|
Before Width: | Height: | Size: 30 KiB |
@ -2,150 +2,4 @@
|
||||
The `compliments` module is one of the default modules of the MagicMirror.
|
||||
This module displays a random compliment.
|
||||
|
||||
## Screenshots
|
||||
- Compliments Screenshot
|
||||

|
||||
|
||||
## Using the module
|
||||
|
||||
To use this module, add it to the modules array in the `config/config.js` file:
|
||||
````javascript
|
||||
modules: [
|
||||
{
|
||||
module: "compliments",
|
||||
position: "lower_third", // This can be any of the regions.
|
||||
// Best results in one of the middle regions like: lower_third
|
||||
config: {
|
||||
// The config property is optional.
|
||||
// If no config is set, the default compliments are shown.
|
||||
// See 'Configuration options' for more information.
|
||||
}
|
||||
}
|
||||
]
|
||||
````
|
||||
|
||||
## Configuration options
|
||||
|
||||
The following properties can be configured:
|
||||
|
||||
|
||||
| Option | Description
|
||||
| ---------------- | -----------
|
||||
| `updateInterval` | How often does the compliment have to change? (Milliseconds) <br><br> **Possible values:** `1000` - `86400000` <br> **Default value:** `30000` (30 seconds)
|
||||
| `fadeSpeed` | Speed of the update animation. (Milliseconds) <br><br> **Possible values:**`0` - `5000` <br> **Default value:** `4000` (4 seconds)
|
||||
| `compliments` | The list of compliments. <br><br> **Possible values:** An object with four arrays: `morning`, `afternoon`, `evening` and `anytime`. See _compliment configuration_ below. <br> **Default value:** See _compliment configuration_ below.
|
||||
| `remoteFile` | External file from which to load the compliments <br><br> **Possible values:** Path or URL (starting with `http://` or `https://`) to a JSON file containing compliments, configured as per the value of the _compliments configuration_ (see below). An object with four arrays: `morning`, `afternoon`, `evening` and `anytime`. - `compliments.json` <br> **Default value:** `null` (Do not load from file)
|
||||
| `classes` | Override the CSS classes of the div showing the compliments <br><br> **Default value:** `thin xlarge bright`
|
||||
| `morningStartTime` | Time in hours (in 24 format), after which the mode of "morning" will begin <br> **Possible values:** `0` - `24` <br><br> **Default value:** `3`
|
||||
| `morningEndTime` | Time in hours (in 24 format), after which the mode of "morning" will end <br> **Possible values:** `0` - `24` <br><br> **Default value:** `12`
|
||||
| `afternoonStartTime` | Time in hours (in 24 format), after which the mode "afternoon" will begin <br> **Possible values:** `0` - `24` <br><br> **Default value:** `12`
|
||||
| `afternoonEndTime` | Time in hours (in 24 format), after which the mode "afternoon" will end <br> **Possible values:** `0` - `24` <br><br> **Default value:** `17`
|
||||
|
||||
All the rest of the time that does not fall into the morningStartTime-morningEndTime and afternoonStartTime-afternoonEndTime ranges is considered "evening".
|
||||
|
||||
### Compliment configuration
|
||||
|
||||
The `compliments` property contains an object with four arrays: <code>morning</code>, <code>afternoon</code>, <code>evening</code> and <code>anytime</code>. Based on the time of the day, the compliments will be picked out of one of these arrays. The arrays contain one or multiple compliments.
|
||||
|
||||
|
||||
If use the currentweather is possible use a actual weather for set compliments. The availables properties are:
|
||||
- `day_sunny`
|
||||
- `day_cloudy`
|
||||
- `cloudy`
|
||||
- `cloudy_windy`
|
||||
- `showers`
|
||||
- `rain`
|
||||
- `thunderstorm`
|
||||
- `snow`
|
||||
- `fog`
|
||||
- `night_clear`
|
||||
- `night_cloudy`
|
||||
- `night_showers`
|
||||
- `night_rain`
|
||||
- `night_thunderstorm`
|
||||
- `night_snow`
|
||||
- `night_alt_cloudy_windy`
|
||||
|
||||
#### Example use with currentweather module
|
||||
````javascript
|
||||
config: {
|
||||
compliments: {
|
||||
day_sunny: [
|
||||
"Today is a sunny day",
|
||||
"It's a beautiful day"
|
||||
],
|
||||
snow: [
|
||||
"Snowball battle!"
|
||||
],
|
||||
rain: [
|
||||
"Don't forget your umbrella"
|
||||
]
|
||||
}
|
||||
}
|
||||
````
|
||||
|
||||
|
||||
#### Default value:
|
||||
````javascript
|
||||
config: {
|
||||
compliments: {
|
||||
anytime: [
|
||||
"Hey there sexy!"
|
||||
],
|
||||
morning: [
|
||||
"Good morning, handsome!",
|
||||
"Enjoy your day!",
|
||||
"How was your sleep?"
|
||||
],
|
||||
afternoon: [
|
||||
"Hello, beauty!",
|
||||
"You look sexy!",
|
||||
"Looking good today!"
|
||||
],
|
||||
evening: [
|
||||
"Wow, you look hot!",
|
||||
"You look nice!",
|
||||
"Hi, sexy!"
|
||||
]
|
||||
}
|
||||
}
|
||||
````
|
||||
|
||||
#### Multi-line compliments:
|
||||
Use `\n` to split compliment text into multiple lines, e.g. `First line.\nSecond line.` will be shown as:
|
||||
```
|
||||
First line.
|
||||
Second line.
|
||||
```
|
||||
|
||||
### External Compliment File
|
||||
You may specify an external file that contains the three compliment arrays. This is particularly useful if you have a
|
||||
large number of compliments and do not wish to crowd your `config.js` file with a large array of compliments.
|
||||
Adding the `remoteFile` variable will override an array you specify in the configuration file.
|
||||
|
||||
This file must be straight JSON. Note that the array names need quotes
|
||||
around them ("morning", "afternoon", "evening", "snow", "rain", etc.).
|
||||
#### Example compliments.json file:
|
||||
````json
|
||||
{
|
||||
"anytime" : [
|
||||
"Hey there sexy!"
|
||||
],
|
||||
"morning" : [
|
||||
"Good morning, sunshine!",
|
||||
"Who needs coffee when you have your smile?",
|
||||
"Go get 'em, Tiger!"
|
||||
],
|
||||
"afternoon" : [
|
||||
"Hitting your stride!",
|
||||
"You are making a difference!",
|
||||
"You're more fun than bubble wrap!"
|
||||
],
|
||||
"evening" : [
|
||||
"You made someone smile today, I know it.",
|
||||
"You are making a difference.",
|
||||
"The day was better for your efforts."
|
||||
]
|
||||
}
|
||||
````
|
||||
|
||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/compliments.html).
|
Before Width: | Height: | Size: 26 KiB |
@ -2,88 +2,4 @@
|
||||
The `currentweather` module is one of the default modules of the MagicMirror.
|
||||
This module displays the current weather, including the windspeed, the sunset or sunrise time, the temperature and an icon to display the current conditions.
|
||||
|
||||
## Screenshot
|
||||
|
||||
- Current weather screenshot
|
||||

|
||||
|
||||
## Using the module
|
||||
|
||||
To use this module, add it to the modules array in the `config/config.js` file:
|
||||
````javascript
|
||||
modules: [
|
||||
{
|
||||
module: "currentweather",
|
||||
position: "top_right", // This can be any of the regions.
|
||||
// Best results in left or right regions.
|
||||
config: {
|
||||
// See 'Configuration options' for more information.
|
||||
location: "Amsterdam,Netherlands",
|
||||
locationID: "", //Location ID from http://bulk.openweathermap.org/sample/city.list.json.gz
|
||||
appid: "abcde12345abcde12345abcde12345ab" //openweathermap.org API key.
|
||||
}
|
||||
}
|
||||
]
|
||||
````
|
||||
|
||||
## Configuration options
|
||||
|
||||
The following properties can be configured:
|
||||
|
||||
|
||||
| Option | Description
|
||||
| ---------------------------- | -----------
|
||||
| `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.
|
||||
| `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.
|
||||
| `appid` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account. <br><br> This value is **REQUIRED**
|
||||
| `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`
|
||||
| `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)
|
||||
| `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`
|
||||
| `showWindDirection` | Show the wind direction next to the wind speed. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `showWindDirectionAsArrow` | Show the wind direction as an arrow instead of abbreviation <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||
| `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`
|
||||
| `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`
|
||||
| `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:** `.`
|
||||
| `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`
|
||||
| `retryDelay` | The delay before retrying after a request failure. (Milliseconds) <br><br> **Possible values:** `1000` - `60000` <br> **Default value:** `2500`
|
||||
| `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> **Default value:** `'weather'`
|
||||
| `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`
|
||||
| `useLocationAsHeader` | If set to `true` and location is given a value, the value of location will be used as the header. This is useful if `locationName` was not returned. <br><br> **Default value:** `false`
|
||||
| `calendarClass` | The class for the calender module to base the event based weather information on. <br><br> **Default value:** `'calendar'`
|
||||
| `iconTable` | The conversion table to convert the weather conditions to weather-icons. <br><br> **Default value:** view tabel below.
|
||||
|
||||
#### Default Icon Table
|
||||
````javascript
|
||||
iconTable: {
|
||||
'01d': 'wi-day-sunny',
|
||||
'02d': 'wi-day-cloudy',
|
||||
'03d': 'wi-cloudy',
|
||||
'04d': 'wi-cloudy-windy',
|
||||
'09d': 'wi-showers',
|
||||
'10d': 'wi-rain',
|
||||
'11d': 'wi-thunderstorm',
|
||||
'13d': 'wi-snow',
|
||||
'50d': 'wi-fog',
|
||||
'01n': 'wi-night-clear',
|
||||
'02n': 'wi-night-cloudy',
|
||||
'03n': 'wi-night-cloudy',
|
||||
'04n': 'wi-night-cloudy',
|
||||
'09n': 'wi-night-showers',
|
||||
'10n': 'wi-night-rain',
|
||||
'11n': 'wi-night-thunderstorm',
|
||||
'13n': 'wi-night-snow',
|
||||
'50n': 'wi-night-alt-cloudy-windy'
|
||||
}
|
||||
````
|
||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/currentweather.html).
|
Before Width: | Height: | Size: 38 KiB |
@ -1,25 +1,4 @@
|
||||
# Module: Hello World
|
||||
The `helloworld` module is one of the default modules of the MagicMirror. It is a simple way to display a static text on the mirror.
|
||||
## Using the module
|
||||
|
||||
To use this module, add it to the modules array in the `config/config.js` file:
|
||||
````javascript
|
||||
modules: [
|
||||
{
|
||||
module: "helloworld",
|
||||
position: "bottom_bar", // This can be any of the regions.
|
||||
config: {
|
||||
// See 'Configuration options' for more information.
|
||||
text: "Hello world!"
|
||||
}
|
||||
}
|
||||
]
|
||||
````
|
||||
|
||||
## Configuration options
|
||||
|
||||
The following properties can be configured:
|
||||
|
||||
| Option | Description
|
||||
| ------ | -----------
|
||||
| `text` | The text to display. <br><br> **Example:** `'Hello world!'` <br> **Default value:** `'Hello world!'`
|
||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/helloworld.html).
|
@ -2,106 +2,4 @@
|
||||
The `newsfeed ` module is one of the default modules of the MagicMirror.
|
||||
This module displays news headlines based on an RSS feed. Scrolling through news headlines happens time-based (````updateInterval````), but can also be controlled by sending news feed specific notifications to the module.
|
||||
|
||||
## Screenshot
|
||||
- News Feed Screenshot using the NYT
|
||||

|
||||
|
||||
## Using the module
|
||||
|
||||
### Configuration
|
||||
To use this module, add it to the modules array in the `config/config.js` file:
|
||||
````javascript
|
||||
modules: [
|
||||
{
|
||||
module: "newsfeed",
|
||||
position: "bottom_bar", // This can be any of the regions. Best results in center regions.
|
||||
config: {
|
||||
// The config property is optional.
|
||||
// If no config is set, an example calendar is shown.
|
||||
// See 'Configuration options' for more information.
|
||||
|
||||
feeds: [
|
||||
{
|
||||
title: "New York Times",
|
||||
url: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml",
|
||||
},
|
||||
{
|
||||
title: "BBC",
|
||||
url: "http://feeds.bbci.co.uk/news/video_and_audio/news_front_page/rss.xml?edition=uk",
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
````
|
||||
|
||||
### Notifications
|
||||
#### Interacting with the module
|
||||
MagicMirror's [notification mechanism](https://github.com/MichMich/MagicMirror/tree/master/modules#thissendnotificationnotification-payload) allows to send notifications to the `newsfeed` module. The following notifications are supported:
|
||||
|
||||
| Notification Identifier | Description
|
||||
| ----------------------- | -----------
|
||||
| `ARTICLE_NEXT` | Shows the next news title (hiding the summary or previously fully displayed article)
|
||||
| `ARTICLE_PREVIOUS` | Shows the previous news title (hiding the summary or previously fully displayed article)
|
||||
| `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` | Toggles 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.
|
||||
|
||||
#### Notifications sent by the module
|
||||
MagicMirror's [notification mechanism](https://github.com/MichMich/MagicMirror/tree/master/modules#thissendnotificationnotification-payload) can also be used to send notifications from the current module to all other modules. The following notifications are broadcasted from this module:
|
||||
|
||||
| Notification Identifier | Description
|
||||
| ----------------------- | -----------
|
||||
| `NEWS_FEED` | Broadcast the current list of news items.
|
||||
| `NEWS_FEED_UPDATE` | Broadcasts the list of updates news items.
|
||||
|
||||
Note the payload of the sent notification event is ignored.
|
||||
|
||||
#### Example
|
||||
The following example shows how the next news article title can be displayed on the MagicMirror.
|
||||
````javascript
|
||||
this.sendNotification('ARTICLE_NEXT');
|
||||
````
|
||||
|
||||
#### `newsfeed` specific notification emitting modules
|
||||
The third party [MMM-Gestures](https://github.com/thobach/MMM-Gestures) module supports above notifications when moving your hand up, down, left or right in front of a gesture sensor attached to the MagicMirror. See module's readme for more details.
|
||||
|
||||
## Configuration options
|
||||
|
||||
The following properties can be configured:
|
||||
|
||||
| Option | Description
|
||||
| ------------------ | -----------
|
||||
| `feeds` | An array of feed urls that will be used as source. <br> More info about this object can be found below. <br> **Default value:** `[{ title: "New York Times", url: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml", encoding: "UTF-8" }]`<br>You can add `reloadInterval` option to set particular reloadInterval to a feed.
|
||||
| `showSourceTitle` | Display the title of the source. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `showPublishDate` | Display the publish date of an headline. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `broadcastNewsFeeds` | Gives the ability to broadcast news feeds to all modules, by using ```sendNotification()``` when set to `true`, rather than ```sendSocketNotification()``` when `false` <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `broadcastNewsUpdates` | Gives the ability to broadcast news feed updates to all modules <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `showDescription` | Display the description of an item. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||
| `wrapTitle` | Wrap the title of the item to multiple lines. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `wrapDescription` | Wrap the description of the item to multiple lines. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `truncDescription` | Truncate description? <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `lengthDescription`| How many characters to be displayed for a truncated description? <br><br> **Possible values:** `1` - `500` <br> **Default value:** `400`
|
||||
| `hideLoading` | Hide module instead of showing LOADING status. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||
| `reloadInterval` | How often does the content needs to be fetched? (Milliseconds) <br><br> **Possible values:** `1000` - `86400000` <br> **Default value:** `300000` (5 minutes)
|
||||
| `updateInterval` | How often do you want to display a new headline? (Milliseconds) <br><br> **Possible values:**`1000` - `60000` <br> **Default value:** `10000` (10 seconds)
|
||||
| `animationSpeed` | Speed of the update animation. (Milliseconds) <br><br> **Possible values:**`0` - `5000` <br> **Default value:** `2500` (2.5 seconds)
|
||||
| `maxNewsItems` | Total amount of news items to cycle through. (0 for unlimited) <br><br> **Possible values:**`0` - `...` <br> **Default value:** `0`
|
||||
| `ignoreOldItems` | Ignore news items that are outdated. <br><br> **Possible values:**`true` or `false` <br> **Default value:** `false`
|
||||
| `ignoreOlderThan` | How old should news items be before they are considered outdated? (Milliseconds) <br><br> **Possible values:**`1` - `...` <br> **Default value:** `86400000` (1 day)
|
||||
| `removeStartTags` | Some news feeds feature tags at the **beginning** of their titles or descriptions, such as _[VIDEO]_. This setting allows for the removal of specified tags from the beginning of an item's description and/or title. <br><br> **Possible values:**`'title'`, `'description'`, `'both'`
|
||||
| `startTags` | List the tags you would like to have removed at the beginning of the feed item <br><br> **Possible values:** `['TAG']` or `['TAG1','TAG2',...]`
|
||||
| `removeEndTags` | Remove specified tags from the **end** of an item's description and/or title. <br><br> **Possible values:**`'title'`, `'description'`, `'both'`
|
||||
| `endTags` | List the tags you would like to have removed at the end of the feed item <br><br> **Possible values:** `['TAG']` or `['TAG1','TAG2',...]`
|
||||
| `prohibitedWords` | Remove news feed item if one of these words is found anywhere in the title (case insensitive and greedy matching) <br><br> **Possible values:** `['word']` or `['word1','word2',...]`
|
||||
| `scrollLength` | Scrolls the full news article page by a given number of pixels when a `ARTICLE_MORE_DETAILS` notification is received and the full news article is already displayed.<br><br> **Possible values:** `1` or `10000` <br> **Default value:** `500`
|
||||
| `logFeedWarnings` | Log warnings when there is an error parsing a news article. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||
|
||||
The `feeds` property contains an array with multiple objects. These objects have the following properties:
|
||||
|
||||
| Option | Description
|
||||
| ---------- | -----------
|
||||
| `title` | The name of the feed source to be displayed above the news items. <br><br> This property is optional.
|
||||
| `url` | The url of the feed used for the headlines. <br><br> **Example:** `'http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml'`
|
||||
| `encoding` | The encoding of the news feed. <br><br> This property is optional. <br> **Possible values:**`'UTF-8'`, `'ISO-8859-1'`, etc ... <br> **Default value:** `'UTF-8'`
|
||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/newsfeed.html).
|
Before Width: | Height: | Size: 44 KiB |
@ -2,26 +2,4 @@
|
||||
The `updatenotification` module is one of the default modules of the MagicMirror.
|
||||
This will display a message whenever a new version of the MagicMirror application is available.
|
||||
|
||||
## Using the module
|
||||
|
||||
To use this module, add it to the modules array in the `config/config.js` file:
|
||||
````javascript
|
||||
modules: [
|
||||
{
|
||||
module: "updatenotification",
|
||||
position: "top_center", // This can be any of the regions.
|
||||
config: {
|
||||
// The config property is optional.
|
||||
// See 'Configuration options' for more information.
|
||||
}
|
||||
}
|
||||
]
|
||||
````
|
||||
|
||||
## Configuration options
|
||||
|
||||
The following properties can be configured:
|
||||
|
||||
| Option | Description
|
||||
| ---------------- | -----------
|
||||
| `updateInterval` | How often do you want to check for a new version? This value represents the interval in milliseconds. <br><br> **Possible values:** Any value above `60000` (1 minute) <br> **Default value:** `600000` (10 minutes);
|
||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/updatenotification.html).
|
@ -2,119 +2,4 @@
|
||||
|
||||
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 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.
|
||||
|
||||
## Example
|
||||
|
||||
 
|
||||
|
||||
## Usage
|
||||
|
||||
To use this module, add it to the modules array in the `config/config.js` file:
|
||||
|
||||
````javascript
|
||||
modules: [
|
||||
{
|
||||
module: "weather",
|
||||
position: "top_right",
|
||||
config: {
|
||||
// See 'Configuration options' for more information.
|
||||
type: 'current'
|
||||
}
|
||||
}
|
||||
]
|
||||
````
|
||||
|
||||
## Configuration options
|
||||
|
||||
The following properties can be configured:
|
||||
|
||||
### General options
|
||||
|
||||
| Option | Description
|
||||
| ---------------------------- | -----------
|
||||
| `weatherProvider` | Which weather provider should be used. <br><br> **Possible values:** `openweathermap` , `darksky` , `weathergov` or `ukmetoffice`<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`
|
||||
| `tempUnits` | What units to use for temperature. If specified overrides `units` setting. Specified by config.js <br><br> **Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` = Fahrenheit <br> **Default value:** `units`
|
||||
| `windUnits` | What units to use for wind speed. If specified overrides `units` setting. Specified by config.js <br><br> **Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` = Fahrenheit <br> **Default value:** `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, 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)
|
||||
| `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 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
|
||||
|
||||
| Option | Description
|
||||
| ---------------------------- | -----------
|
||||
| `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`
|
||||
| `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`
|
||||
| `showWindDirection` | Show the wind direction next to the wind speed. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||
| `showWindDirectionAsArrow` | Show the wind direction as an arrow instead of abbreviation <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||
| `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`
|
||||
|
||||
#### 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`
|
||||
| `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`, `/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**
|
||||
|
||||
### 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**
|
||||
|
||||
### 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**
|
||||
|
||||
### UK Met Office options
|
||||
|
||||
| Option | Description
|
||||
| ---------------------------- | -----------
|
||||
| `apiBase` | The UKMO base URL. <br><br> **Possible value:** `'http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/'` <br> This value is **REQUIRED**
|
||||
| `locationId` | The UKMO API location code. <br><br> **Possible values:** `322942` <br> This value is **REQUIRED**
|
||||
| `apiKey` | The [UK Met Office](https://www.metoffice.gov.uk/datapoint/getting-started) API key, which can be obtained by creating an UKMO Datapoint account. <br><br> This value is **REQUIRED**
|
||||
|
||||
## API Provider Development
|
||||
|
||||
If you want to add another API provider checkout the [Guide](providers).
|
||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/weather.html).
|
Before Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 16 KiB |
@ -2,81 +2,4 @@
|
||||
The `weatherforecast` module is one of the default modules of the MagicMirror.
|
||||
This module displays the weather forecast for the coming week, including an an icon to display the current conditions, the minimum temperature and the maximum temperature.
|
||||
|
||||
## Screenshots
|
||||
|
||||
- 5 day forecast
|
||||

|
||||
|
||||
## Using the module
|
||||
|
||||
To use this module, add it to the modules array in the `config/config.js` file:
|
||||
````javascript
|
||||
modules: [
|
||||
{
|
||||
module: "weatherforecast",
|
||||
position: "top_right", // This can be any of the regions.
|
||||
// Best results in left or right regions.
|
||||
config: {
|
||||
// See 'Configuration options' for more information.
|
||||
location: "Amsterdam,Netherlands",
|
||||
locationID: "", //Location ID from http://bulk.openweathermap.org/sample/city.list.json.gz
|
||||
appid: "abcde12345abcde12345abcde12345ab" //openweathermap.org API key.
|
||||
}
|
||||
}
|
||||
]
|
||||
````
|
||||
|
||||
## Configuration options
|
||||
|
||||
The following properties can be configured:
|
||||
|
||||
| Option | Description
|
||||
| ---------------------------- | -----------
|
||||
| `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.
|
||||
| `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.
|
||||
| `appid` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account. <br><br> This value is **REQUIRED**
|
||||
| `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 values to nearest integer. <br><br> **Possible values:** `true` (round to integer) or `false` (display exact value with decimal point) <br> **Default value:** `false`
|
||||
| `maxNumberOfDays` | How many days of forecast to return. Specified by config.js <br><br> **Possible values:** `1` - `16` <br> **Default value:** `7` (7 days) <br> This value is optional. By default the weatherforecast module will return 7 days.
|
||||
| `showRainAmount` | Should the predicted rain amount be displayed? <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false` <br> This value is optional. By default the weatherforecast module will not display the predicted amount of rain.
|
||||
| `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)
|
||||
| `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:** `.`
|
||||
| `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`
|
||||
| `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:** `2500` (2.5 seconds delay. This delay is used to keep the OpenWeather API happy.)
|
||||
| `retryDelay` | The delay before retrying after a request failure. (Milliseconds) <br><br> **Possible values:** `1000` - `60000` <br> **Default value:** `2500`
|
||||
| `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/'`
|
||||
| `forecastEndpoint` | The OpenWeatherMap API endPoint. <br><br> **Default value:** `'forecast/daily'`
|
||||
| `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 calendar module to base the event based weather information on. <br><br> **Default value:** `'calendar'`
|
||||
| `tableClass` | Name of the classes issued from `main.css`. <br><br> **Possible values:** xsmall, small, medium, large, xlarge. <br> **Default value:** _small._
|
||||
| `iconTable` | The conversion table to convert the weather conditions to weather-icons. <br><br> **Default value:** view table below
|
||||
| `colored` | If set `colored` to `true` the min-temp gets a blue tone and the max-temp gets a red tone. <br><br> **Default value:** `'false'`
|
||||
| `scale ` | If set to `true` the module will display `C` for Celsius degrees and `F` for Fahrenheit degrees after the number, based on the value of the `units` option, otherwise only the ° character is displayed. <br><br> **Default value:** `false`
|
||||
|
||||
#### Default Icon Table
|
||||
````javascript
|
||||
iconTable: {
|
||||
'01d': 'wi-day-sunny',
|
||||
'02d': 'wi-day-cloudy',
|
||||
'03d': 'wi-cloudy',
|
||||
'04d': 'wi-cloudy-windy',
|
||||
'09d': 'wi-showers',
|
||||
'10d': 'wi-rain',
|
||||
'11d': 'wi-thunderstorm',
|
||||
'13d': 'wi-snow',
|
||||
'50d': 'wi-fog',
|
||||
'01n': 'wi-night-clear',
|
||||
'02n': 'wi-night-cloudy',
|
||||
'03n': 'wi-night-cloudy',
|
||||
'04n': 'wi-night-cloudy',
|
||||
'09n': 'wi-night-showers',
|
||||
'10n': 'wi-night-rain',
|
||||
'11n': 'wi-night-thunderstorm',
|
||||
'13n': 'wi-night-snow',
|
||||
'50n': 'wi-night-alt-cloudy-windy'
|
||||
}
|
||||
````
|
||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/weatherforecast.html).
|
Before Width: | Height: | Size: 84 KiB |
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "magicmirror",
|
||||
"version": "2.10.1",
|
||||
"version": "2.11.0-develop",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "magicmirror",
|
||||
"version": "2.10.1",
|
||||
"version": "2.11.0-develop",
|
||||
"description": "The open source modular smart mirror platform.",
|
||||
"main": "js/electron.js",
|
||||
"scripts": {
|
||||
|
@ -2,6 +2,13 @@
|
||||
# use bash instead of sh
|
||||
./untrack-css.sh
|
||||
|
||||
if grep docker /proc/1/cgroup -qa; then
|
||||
# if running in docker, only start electron
|
||||
|
||||
electron js/electron.js $1;
|
||||
else
|
||||
# not running in docker
|
||||
|
||||
if [ -z "$DISPLAY" ]; then #If not set DISPLAY is SSH remote or tty
|
||||
export DISPLAY=:0 # Set by default display
|
||||
fi
|
||||
@ -65,3 +72,4 @@ else
|
||||
# we can use electron directly
|
||||
electron js/electron.js $1;
|
||||
fi
|
||||
fi
|
@ -28,6 +28,9 @@
|
||||
|
||||
"UPDATE_NOTIFICATION": "MagicMirror² päivitys saatavilla.",
|
||||
"UPDATE_NOTIFICATION_MODULE": "Päivitys saatavilla moduulille {MODULE_NAME}.",
|
||||
"UPDATE_INFO_SINGLE": "Nykyasennus on {COMMIT_COUNT} muutoksen jäljessä {BRANCH_NAME} haaraan nähden.",
|
||||
"UPDATE_INFO_MULTIPLE": "Nykyasennus on {COMMIT_COUNT} muutosta jäljessä {BRANCH_NAME} haaraan nähden.",
|
||||
|
||||
"FEELS": "Tuntuu kuin"
|
||||
"FEELS": "Tuntuu kuin",
|
||||
"PRECIP": "Sateen todennäköisyys"
|
||||
}
|
||||
|