mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-08-21 12:55:22 +00:00
@@ -17,6 +17,7 @@
|
|||||||
},
|
},
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"sourceType": "module",
|
"sourceType": "module",
|
||||||
|
"ecmaVersion": 2017,
|
||||||
"ecmaFeatures": {
|
"ecmaFeatures": {
|
||||||
"globalReturn": true
|
"globalReturn": true
|
||||||
}
|
}
|
||||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@@ -11,7 +11,9 @@ coverage
|
|||||||
.grunt
|
.grunt
|
||||||
.lock-wscript
|
.lock-wscript
|
||||||
build/Release
|
build/Release
|
||||||
node_modules
|
/node_modules/**/*
|
||||||
|
fonts/node_modules/**/*
|
||||||
|
vendor/node_modules/**/*
|
||||||
jspm_modules
|
jspm_modules
|
||||||
.npm
|
.npm
|
||||||
.node_repl_history
|
.node_repl_history
|
||||||
@@ -81,3 +83,5 @@ Temporary Items
|
|||||||
*.orig
|
*.orig
|
||||||
*.rej
|
*.rej
|
||||||
*.bak
|
*.bak
|
||||||
|
|
||||||
|
!/tests/node_modules/**/*
|
@@ -1,3 +1,4 @@
|
|||||||
|
dist: trusty
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- "8"
|
- "8"
|
||||||
|
35
CHANGELOG.md
35
CHANGELOG.md
@@ -3,21 +3,52 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- new upgrade script to help users consume regular updates installers/upgrade-script.sh
|
||||||
|
- new script to help setup pm2, without install installers/fixuppm2.sh
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
- updated raspberry.sh installer script to handle new platform issues, split node/npm, pm2, and screen saver changes
|
||||||
|
- improve handling for armv6l devices, where electron support has gone away, add optional serveronly config option
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/donate) With your help we can continue to improve the MagicMirror² core.
|
❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/donate) With your help we can continue to improve the MagicMirror² core.
|
||||||
|
|
||||||
## [2.9.0] - Unreleased (Develop Branch)
|
## [2.10.0] - Unreleased (Develop Branch)
|
||||||
|
|
||||||
*This release is scheduled to be released on 2019-10-01.*
|
*This release is scheduled to be released on 2020-01-01.*
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
- Timestamps in log output
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed issue in weatherforecast module where predicted amount of rain was not using the decimal symbol specified in config.js.
|
||||||
|
|
||||||
|
## [2.9.0] - 2019-10-01
|
||||||
|
|
||||||
|
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues running Electron, make sure your [Raspbian is up to date](https://www.raspberrypi.org/documentation/raspbian/updating.md).
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Spanish translation for "PRECIP".
|
||||||
|
- Adding a Malay (Malaysian) translation for MagicMirror².
|
||||||
|
- Add test check URLs of vendors 200 and 404 HTTP CODE.
|
||||||
|
- Add tests for new weather module and helper to stub ajax requests.
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
- Updatenotification module: Display update notification for a limited (configurable) time.
|
- Updatenotification module: Display update notification for a limited (configurable) time.
|
||||||
|
- Enabled e2e/vendor_spec.js tests.
|
||||||
|
- The css/custom.css will be rename after the next release. We've add into `run-start.sh` a instruction by GIT to ignore with `--skip-worktree` and `rm --cached`. [#1540](https://github.com/MichMich/MagicMirror/issues/1540)
|
||||||
|
- Disable sending of notification CLOCK_SECOND when displaySeconds is false.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Updatenotification module: Properly handle race conditions, prevent crash.
|
- Updatenotification module: Properly handle race conditions, prevent crash.
|
||||||
|
- Send `NEWS_FEED` notification also for the first news messages which are shown.
|
||||||
|
- Fixed issue where weather module would not refresh data after a network or API outage. [#1722](https://github.com/MichMich/MagicMirror/issues/1722)
|
||||||
|
- Fixed weatherforecast module not displaying rain amount on fallback endpoint.
|
||||||
|
- Notifications CLOCK_SECOND & CLOCK_MINUTE being from startup instead of matched against the clock and avoid drifting.
|
||||||
|
|
||||||
## [2.8.0] - 2019-07-01
|
## [2.8.0] - 2019-07-01
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
Copyright © 2016-2017 Michael Teeuw
|
Copyright © 2016-2019 Michael Teeuw
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
Permission is hereby granted, free of charge, to any person
|
||||||
obtaining a copy of this software and associated documentation
|
obtaining a copy of this software and associated documentation
|
||||||
|
15
README.md
15
README.md
@@ -177,14 +177,19 @@ For more available modules, check out out the wiki page [MagicMirror² 3rd Party
|
|||||||
|
|
||||||
If you want to update your MagicMirror² to the latest version, use your terminal to go to your Magic Mirror folder and type the following command:
|
If you want to update your MagicMirror² to the latest version, use your terminal to go to your Magic Mirror folder and type the following command:
|
||||||
|
|
||||||
```bash
|
|
||||||
git pull && npm install
|
|
||||||
```
|
```
|
||||||
|
bash -c "$(curl -sL https://raw.githubusercontent.com/MichMich/MagicMirror/master/installers/upgrade-script.sh)"
|
||||||
|
```
|
||||||
|
This will do a test run
|
||||||
|
|
||||||
If you changed nothing more than the config or the modules, this should work without any problems.
|
If the test update looks good then run this command
|
||||||
Type `git status` to see your changes, if there are any, you can reset them with `git reset --hard`. After that, git pull should be possible.
|
```
|
||||||
|
bash -c "$(curl -sL https://raw.githubusercontent.com/MichMich/MagicMirror/master/installers/upgrade-script.sh)" apply
|
||||||
|
```
|
||||||
|
If there are changes you have made, they will be listed, and u will have the opportunity to save your work
|
||||||
|
|
||||||
|
The script will also update the dependencies of any active modules
|
||||||
|
If there are update issues, please come to the forums for help
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
The community around the MagicMirror² is constantly growing. We even have a [forum](https://forum.magicmirror.builders) now where you can share your ideas, ask questions, help others and get inspired by other builders. We would love to see you there!
|
The community around the MagicMirror² is constantly growing. We even have a [forum](https://forum.magicmirror.builders) now where you can share your ideas, ask questions, help others and get inspired by other builders. We would love to see you there!
|
||||||
|
@@ -24,6 +24,11 @@ var config = {
|
|||||||
language: "en",
|
language: "en",
|
||||||
timeFormat: 24,
|
timeFormat: 24,
|
||||||
units: "metric",
|
units: "metric",
|
||||||
|
// serverOnly: true/false/"local" ,
|
||||||
|
// local for armv6l processors, default
|
||||||
|
// starts serveronly and then starts chrome browser
|
||||||
|
// false, default for all NON-armv6l devices
|
||||||
|
// true, force serveronly mode, because you want to.. no UI on this device
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
{
|
{
|
||||||
|
@@ -1,14 +0,0 @@
|
|||||||
/*****************************************************
|
|
||||||
* Magic Mirror *
|
|
||||||
* Custom CSS *
|
|
||||||
* *
|
|
||||||
* By Michael Teeuw http://michaelteeuw.nl *
|
|
||||||
* MIT Licensed. *
|
|
||||||
* *
|
|
||||||
* Add any custom CSS below. *
|
|
||||||
* Changes to this files will be ignored by GIT. *
|
|
||||||
*****************************************************/
|
|
||||||
|
|
||||||
body {
|
|
||||||
|
|
||||||
}
|
|
15
installers/dumpactivemodules.js
Normal file
15
installers/dumpactivemodules.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
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) {}
|
||||||
|
}
|
||||||
|
}
|
161
installers/fixuppm2.sh
Executable file
161
installers/fixuppm2.sh
Executable file
@@ -0,0 +1,161 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Define the tested version of Node.js.
|
||||||
|
NODE_TESTED="v5.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
|
||||||
|
date +"pm2 setup starting - %a %b %e %H:%M:%S %Z %Y" >>$logfile
|
||||||
|
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 command = $v >>$logfile
|
||||||
|
# execute the command returned
|
||||||
|
$v 2>/dev/null >>$logfile
|
||||||
|
echo pm2 startup done >>$logfile
|
||||||
|
|
||||||
|
# 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
|
382
installers/raspberry.sh
Normal file → Executable file
382
installers/raspberry.sh
Normal file → Executable file
@@ -1,5 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# This is an installer script for MagicMirror2. It works well enough
|
# This is an installer script for MagicMirror2. It works well enough
|
||||||
# that it can detect if you have Node installed, run a binary script
|
# that it can detect if you have Node installed, run a binary script
|
||||||
# and then download and run MagicMirror2.
|
# and then download and run MagicMirror2.
|
||||||
@@ -18,117 +17,169 @@ echo ' \$$$$$$ |'
|
|||||||
echo ' \______/'
|
echo ' \______/'
|
||||||
echo -e "\e[0m"
|
echo -e "\e[0m"
|
||||||
|
|
||||||
|
doInstall=1
|
||||||
|
true=1
|
||||||
|
false=0
|
||||||
# Define the tested version of Node.js.
|
# Define the tested version of Node.js.
|
||||||
NODE_TESTED="v5.1.0"
|
NODE_TESTED="v5.1.0"
|
||||||
NPM_TESTED="V6.0.0"
|
NPM_TESTED="V6.0.0"
|
||||||
USER=`whoami`
|
USER=`whoami`
|
||||||
PM2_FILE=~/MagicMirror/installers/pm2_MagicMirror.json
|
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.
|
# Determine which Pi is running.
|
||||||
|
date +"install starting - %a %b %e %H:%M:%S %Z %Y" >>$logfile
|
||||||
ARM=$(uname -m)
|
ARM=$(uname -m)
|
||||||
|
echo installing on $ARM processor system >>$logfile
|
||||||
# Check the Raspberry Pi version.
|
# Check the Raspberry Pi version.
|
||||||
if [ "$ARM" != "armv7l" ]; then
|
if [ "$ARM" != "armv7l" ]; then
|
||||||
read -p "this appears not to be a Raspberry Pi 2 or 3, do you want to continue installtion (y/N)?" choice
|
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
|
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[91mSorry, your Raspberry Pi is not supported."
|
||||||
echo -e "\e[91mPlease run MagicMirror on a Raspberry Pi 2 or 3."
|
echo -e "\e[91mPlease run MagicMirror on a Raspberry Pi 2 or 3."
|
||||||
echo -e "\e[91mIf this is a Pi Zero, you are in the same boat as the original Raspberry Pi. You must run in server only mode."
|
echo -e "\e[91mIf this is a Pi Zero, you are in the same boat as the original Raspberry Pi. You must run in server only mode."
|
||||||
exit;
|
exit;
|
||||||
fi
|
fi
|
||||||
|
#if [ "$ARM" == "armv6l" ]; then
|
||||||
|
# echo forcing armv71 architecture for pi 0 >>$logfile
|
||||||
|
# force_arch=-'--arch=armv7l'
|
||||||
|
#fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Define helper methods.
|
# Define helper methods.
|
||||||
function command_exists () { type "$1" &> /dev/null ;}
|
function command_exists () { type "$1" &> /dev/null ;}
|
||||||
function verlte() { [ "$1" = "`echo -e "$1\n$2" | sort -V | head -n1`" ];}
|
function verlte() { [ "$1" = "`echo -e "$1\n$2" | sort -V | head -n1`" ];}
|
||||||
function verlt() { [ "$1" = "$2" ] && return 1 || verlte $1 $2 ;}
|
function verlt() { [ "$1" = "$2" ] && return 1 || verlte $1 $2 ;}
|
||||||
|
|
||||||
# Update before first apt-get
|
# Update before first apt-get
|
||||||
echo -e "\e[96mUpdating packages ...\e[90m"
|
if [ $mac != 'Darwin' ]; then
|
||||||
sudo apt-get update || echo -e "\e[91mUpdate failed, carrying on installation ...\e[90m"
|
echo -e "\e[96mUpdating packages ...\e[90m" | tee -a $logfile
|
||||||
|
sudo apt-get update || echo -e "\e[91mUpdate failed, carrying on installation ...\e[90m" | tee -a $logfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $mac != 'Darwin' ]; then
|
||||||
# Installing helper tools
|
# Installing helper tools
|
||||||
echo -e "\e[96mInstalling helper tools ...\e[90m"
|
echo -e "\e[96mInstalling helper tools ...\e[90m" | tee -a $logfile
|
||||||
sudo apt-get --assume-yes install curl wget git build-essential unzip || exit
|
sudo apt-get --assume-yes install curl wget git build-essential unzip || exit
|
||||||
|
fi
|
||||||
|
|
||||||
# Check if we need to install or upgrade Node.js.
|
# Check if we need to install or upgrade Node.js.
|
||||||
echo -e "\e[96mCheck current Node installation ...\e[0m"
|
echo -e "\e[96mCheck current Node installation ...\e[0m" | tee -a $logfile
|
||||||
NODE_INSTALL=false
|
NODE_INSTALL=false
|
||||||
if command_exists node; then
|
if command_exists node; then
|
||||||
echo -e "\e[0mNode currently installed. Checking version number.";
|
echo -e "\e[0mNode currently installed. Checking version number." | tee -a $logfile
|
||||||
NODE_CURRENT=$(node -v)
|
NODE_CURRENT=$(node -v)
|
||||||
echo -e "\e[0mMinimum Node version: \e[1m$NODE_TESTED\e[0m"
|
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"
|
echo -e "\e[0mInstalled Node version: \e[1m$NODE_CURRENT\e[0m" | tee -a $logfile
|
||||||
if verlte $NODE_CURRENT $NODE_TESTED; then
|
if verlte $NODE_CURRENT $NODE_TESTED; then
|
||||||
echo -e "\e[96mNode should be upgraded.\e[0m"
|
echo -e "\e[96mNode should be upgraded.\e[0m" | tee -a $logfile
|
||||||
NODE_INSTALL=true
|
NODE_INSTALL=true
|
||||||
|
|
||||||
# Check if a node process is currenlty running.
|
# Check if a node process is currenlty running.
|
||||||
# If so abort installation.
|
# If so abort installation.
|
||||||
if pgrep "node" > /dev/null; then
|
if pgrep "node" > /dev/null; then
|
||||||
echo -e "\e[91mA Node process is currently running. Can't upgrade."
|
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."
|
echo "Please quit all Node processes and restart the installer." | tee -a $logfile
|
||||||
exit;
|
exit;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
echo -e "\e[92mNo Node.js upgrade necessary.\e[0m"
|
echo -e "\e[92mNo Node.js upgrade necessary.\e[0m" | tee -a $logfile
|
||||||
fi
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
echo -e "\e[93mNode.js is not installed.\e[0m";
|
echo -e "\e[93mNode.js is not installed.\e[0m" | tee -a $logfile
|
||||||
NODE_INSTALL=true
|
NODE_INSTALL=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Install or upgrade node if necessary.
|
# Install or upgrade node if necessary.
|
||||||
if $NODE_INSTALL; then
|
if $NODE_INSTALL; then
|
||||||
|
|
||||||
echo -e "\e[96mInstalling Node.js ...\e[90m"
|
echo -e "\e[96mInstalling Node.js ...\e[90m" | tee -a $logfile
|
||||||
|
|
||||||
# Fetch the latest version of Node.js from the selected branch
|
# 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)
|
# 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.
|
# 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"
|
NODE_STABLE_BRANCH="10.x"
|
||||||
curl -sL https://deb.nodesource.com/setup_$NODE_STABLE_BRANCH | sudo -E bash -
|
curl -sL https://deb.nodesource.com/setup_$NODE_STABLE_BRANCH | sudo -E bash -
|
||||||
sudo apt-get install -y nodejs
|
sudo apt-get install -y nodejs
|
||||||
echo -e "\e[92mNode.js installation Done!\e[0m"
|
fi
|
||||||
|
echo -e "\e[92mNode.js installation Done! version=$(node -v)\e[0m" | tee -a $logfile
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if we need to install or upgrade npm.
|
# Check if we need to install or upgrade npm.
|
||||||
echo -e "\e[96mCheck current NPM installation ...\e[0m"
|
echo -e "\e[96mCheck current NPM installation ...\e[0m" | tee -a $logfile
|
||||||
NPM_INSTALL=false
|
NPM_INSTALL=false
|
||||||
if command_exists npm; then
|
if command_exists npm; then
|
||||||
echo -e "\e[0mNPM currently installed. Checking version number.";
|
echo -e "\e[0mNPM currently installed. Checking version number." | tee -a $logfile
|
||||||
NPM_CURRENT='V'$(npm -v)
|
NPM_CURRENT='V'$(npm -v)
|
||||||
echo -e "\e[0mMinimum npm version: \e[1m$NPM_TESTED\e[0m"
|
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"
|
echo -e "\e[0mInstalled npm version: \e[1m$NPM_CURRENT\e[0m" | tee -a $logfile
|
||||||
if verlte $NPM_CURRENT $NPM_TESTED; then
|
if verlte $NPM_CURRENT $NPM_TESTED; then
|
||||||
echo -e "\e[96mnpm should be upgraded.\e[0m"
|
echo -e "\e[96mnpm should be upgraded.\e[0m" | tee -a $logfile
|
||||||
NPM_INSTALL=true
|
NPM_INSTALL=true
|
||||||
|
|
||||||
# Check if a node process is currently running.
|
# Check if a node process is currently running.
|
||||||
# If so abort installation.
|
# If so abort installation.
|
||||||
if pgrep "npm" > /dev/null; then
|
if pgrep "npm" > /dev/null; then
|
||||||
echo -e "\e[91mA npm process is currently running. Can't upgrade."
|
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."
|
echo "Please quit all npm processes and restart the installer." | tee -a $logfile
|
||||||
exit;
|
exit;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
echo -e "\e[92mNo npm upgrade necessary.\e[0m"
|
echo -e "\e[92mNo npm upgrade necessary.\e[0m" | tee -a $logfile
|
||||||
fi
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
echo -e "\e[93mnpm is not installed.\e[0m";
|
echo -e "\e[93mnpm is not installed.\e[0m" | tee -a $logfile
|
||||||
NPM_INSTALL=true
|
NPM_INSTALL=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Install or upgrade node if necessary.
|
# Install or upgrade node if necessary.
|
||||||
if $NPM_INSTALL; then
|
if $NPM_INSTALL; then
|
||||||
|
|
||||||
echo -e "\e[96mInstalling npm ...\e[90m"
|
echo -e "\e[96mInstalling npm ...\e[90m" | tee -a $logfile
|
||||||
|
|
||||||
# Fetch the latest version of npm from the selected branch
|
# 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)
|
# The NODE_STABLE_BRANCH variable will need to be manually adjusted when a new branch is released. (e.g. 7.x)
|
||||||
@@ -137,108 +188,299 @@ if $NPM_INSTALL; then
|
|||||||
#NODE_STABLE_BRANCH="9.x"
|
#NODE_STABLE_BRANCH="9.x"
|
||||||
#curl -sL https://deb.nodesource.com/setup_$NODE_STABLE_BRANCH | sudo -E bash -
|
#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
|
sudo apt-get install -y npm
|
||||||
echo -e "\e[92mnpm installation Done!\e[0m"
|
fi
|
||||||
|
# update to the latest.
|
||||||
|
echo upgrading npm to latest >> $logfile
|
||||||
|
sudo npm i -g npm
|
||||||
|
echo -e "\e[92mnpm installation Done! version=V$(npm -v)\e[0m" | tee -a $logfile
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Install MagicMirror
|
# Install MagicMirror
|
||||||
cd ~
|
cd ~
|
||||||
|
if [ $doInstall == 1 ]; then
|
||||||
if [ -d "$HOME/MagicMirror" ] ; then
|
if [ -d "$HOME/MagicMirror" ] ; then
|
||||||
echo -e "\e[93mIt seems like MagicMirror is already installed."
|
echo -e "\e[93mIt seems like MagicMirror is already installed." | tee -a $logfile
|
||||||
echo -e "To prevent overwriting, the installer will be aborted."
|
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"
|
echo -e "Please rename the \e[1m~/MagicMirror\e[0m\e[93m folder and try again.\e[0m" | tee -a $logfile
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "If you want to upgrade your installation run \e[1m\e[97mgit pull\e[0m from the ~/MagicMirror directory."
|
echo -e "If you want to upgrade your installation run \e[1m\e[97mgit pull\e[0m from the ~/MagicMirror directory." | tee -a $logfile
|
||||||
echo ""
|
echo ""
|
||||||
exit;
|
exit;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "\e[96mCloning MagicMirror ...\e[90m"
|
echo -e "\e[96mCloning MagicMirror ...\e[90m" | tee -a $logfile
|
||||||
if git clone --depth=1 https://github.com/MichMich/MagicMirror.git; then
|
if git clone --depth=1 https://github.com/MichMich/MagicMirror.git; then
|
||||||
echo -e "\e[92mCloning MagicMirror Done!\e[0m"
|
echo -e "\e[92mCloning MagicMirror Done!\e[0m" | tee -a $logfile
|
||||||
else
|
else
|
||||||
echo -e "\e[91mUnable to clone MagicMirror."
|
echo -e "\e[91mUnable to clone MagicMirror." | tee -a $logfile
|
||||||
exit;
|
exit;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd ~/MagicMirror || exit
|
cd ~/MagicMirror || exit
|
||||||
echo -e "\e[96mInstalling dependencies ...\e[90m"
|
echo -e "\e[96mInstalling dependencies ...\e[90m" | tee -a $logfile
|
||||||
if npm install; then
|
if npm install $force_arch; then
|
||||||
echo -e "\e[92mDependencies installation Done!\e[0m"
|
echo -e "\e[92mDependencies installation Done!\e[0m" | tee -a $logfile
|
||||||
else
|
else
|
||||||
echo -e "\e[91mUnable to install dependencies!"
|
echo -e "\e[91mUnable to install dependencies!" | tee -a $logfile
|
||||||
exit;
|
exit;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Use sample config for start MagicMirror
|
# Use sample config for start MagicMirror
|
||||||
|
echo setting up initial config.js | tee -a $logfile
|
||||||
cp config/config.js.sample config/config.js
|
cp config/config.js.sample config/config.js
|
||||||
|
fi
|
||||||
# Check if plymouth is installed (default with PIXEL desktop environment), then install custom splashscreen.
|
# Check if plymouth is installed (default with PIXEL desktop environment), then install custom splashscreen.
|
||||||
echo -e "\e[96mCheck plymouth installation ...\e[0m"
|
echo -e "\e[96mCheck plymouth installation ...\e[0m" | tee -a $logfile
|
||||||
if command_exists plymouth; then
|
if command_exists plymouth; then
|
||||||
THEME_DIR="/usr/share/plymouth/themes"
|
THEME_DIR="/usr/share/plymouth/themes"
|
||||||
echo -e "\e[90mSplashscreen: Checking themes directory.\e[0m"
|
echo -e "\e[90mSplashscreen: Checking themes directory.\e[0m" | tee -a $logfile
|
||||||
if [ -d $THEME_DIR ]; then
|
if [ -d $THEME_DIR ]; then
|
||||||
echo -e "\e[90mSplashscreen: Create theme directory if not exists.\e[0m"
|
echo -e "\e[90mSplashscreen: Create theme directory if not exists.\e[0m" | tee -a $logfile
|
||||||
if [ ! -d $THEME_DIR/MagicMirror ]; then
|
if [ ! -d $THEME_DIR/MagicMirror ]; then
|
||||||
sudo mkdir $THEME_DIR/MagicMirror
|
sudo mkdir $THEME_DIR/MagicMirror
|
||||||
fi
|
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
|
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 -e "\e[90mSplashscreen: Theme copied successfully.\e[0m"
|
echo -e "\e[90mSplashscreen: Theme copied successfully.\e[0m" | tee -a $logfile
|
||||||
if sudo plymouth-set-default-theme -R MagicMirror; then
|
if sudo plymouth-set-default-theme -R MagicMirror; then
|
||||||
echo -e "\e[92mSplashscreen: Changed theme to MagicMirror successfully.\e[0m"
|
echo -e "\e[92mSplashscreen: Changed theme to MagicMirror successfully.\e[0m" | tee -a $logfile
|
||||||
else
|
else
|
||||||
echo -e "\e[91mSplashscreen: Couldn't change theme to MagicMirror!\e[0m"
|
echo -e "\e[91mSplashscreen: Couldn't change theme to MagicMirror!\e[0m" | tee -a $logfile
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo -e "\e[91mSplashscreen: Copying theme failed!\e[0m"
|
echo -e "\e[91mSplashscreen: Copying theme failed!\e[0m" | tee -a $logfile
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo -e "\e[91mSplashscreen: Themes folder doesn't exist!\e[0m"
|
echo -e "\e[91mSplashscreen: Themes folder doesn't exist!\e[0m" | tee -a $logfile
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo -e "\e[93mplymouth is not installed.\e[0m";
|
echo -e "\e[93mplymouth is not installed.\e[0m" | tee -a $logfile
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Use pm2 control like a service MagicMirror
|
# Use pm2 control like a service MagicMirror
|
||||||
read -p "Do you want use pm2 for auto starting of your MagicMirror (y/N)?" choice
|
read -p "Do you want use pm2 for auto starting of your MagicMirror (y/N)?" choice
|
||||||
if [[ $choice =~ ^[Yy]$ ]]; then
|
if [[ $choice =~ ^[Yy]$ ]]; then
|
||||||
#
|
echo install and setup pm2 | tee -a $logfile
|
||||||
# check if this is a mac
|
# assume pm2 will be found on the path
|
||||||
#
|
pm2cmd=pm2
|
||||||
mac=$(uname -s)
|
# check to see if already installed
|
||||||
|
pm2_installed=$(which $pm2cmd)
|
||||||
up=""
|
up=""
|
||||||
if [ $mac == 'Darwin' ]; then
|
if [ $mac == 'Darwin' ]; then
|
||||||
up="--unsafe-perm"
|
up="--unsafe-perm"
|
||||||
|
launchctl=launchctl
|
||||||
|
launchctl_path=$(which $launchctl)
|
||||||
|
`export PATH=$PATH:${launchctl_path%/$launchctl}`
|
||||||
fi
|
fi
|
||||||
sudo npm install $up -g pm2
|
# check to see if already installed
|
||||||
if [[ "$(ps --no-headers -o comm 1)" =~ systemd ]]; then #Checking for systemd
|
pm2_installed=$(which $pm2cmd)
|
||||||
pm2 startup systemd -u $USER --hp /home/$USER
|
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)
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
else
|
||||||
sudo su -c "env PATH=$PATH:/usr/bin pm2 startup linux -u $USER --hp /home/$USER"
|
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
|
fi
|
||||||
if [ "USER" != "pi" ]; then
|
# edit the pms config file for the right user
|
||||||
sed 's/pi/'$USER'/g' mm.sh >mm.sh
|
echo change $PM2_FILE >>$logfile
|
||||||
sed 's/pi/'$USER'/g' $PM2_FILE > ~/MagicMirror/installers/pm2_MagicMirror_new.json
|
sed 's/pi/'$USER'/g' $PM2_FILE > pm2_MagicMirror_new.json
|
||||||
PM2_FILE=~/MagicMirror/installers/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
|
fi
|
||||||
pm2 start $PM2_FILE
|
echo now using this config file $PM2_FILE >>$logfile
|
||||||
pm2 save
|
# 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
|
fi
|
||||||
# Disable Screensaver
|
# Disable Screensaver
|
||||||
if [ -d "/etc/xdg/lxsession" ]; then
|
choice=n
|
||||||
read -p "Do you want to disable the screen saver? (y/N)?" choice
|
read -p "Do you want to disable the screen saver? (y/N)?" choice
|
||||||
if [[ $choice =~ ^[Yy]$ ]]; then
|
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 [ -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"
|
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
|
export DISPLAY=:0; xset s noblank;xset s off;xset -dpms
|
||||||
|
else
|
||||||
|
echo lxsession screen saver 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 [ -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
|
fi
|
||||||
else
|
else
|
||||||
echo " "
|
echo " "
|
||||||
echo -e "unable to disable screen saver, /etc/xdg/lxsession does not exist"
|
echo -e "unable to disable screen saver, /etc/xdg/lxsession does not exist" | tee -a $logfile
|
||||||
fi
|
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 -e "\e[92mWe're ready! Run \e[1m\e[97mDISPLAY=:0 npm start\e[0m\e[92m from the ~/MagicMirror directory to start your MagicMirror.\e[0m"
|
|
||||||
echo " "
|
echo " "
|
||||||
echo " "
|
echo " "
|
||||||
|
|
||||||
|
date +"install completed - %a %b %e %H:%M:%S %Z %Y" >>$logfile
|
||||||
|
357
installers/upgrade-script.sh
Executable file
357
installers/upgrade-script.sh
Executable file
@@ -0,0 +1,357 @@
|
|||||||
|
#!/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 >>$logfile
|
||||||
|
date +"Upgrade started - %a %b %e %H:%M:%S %Z %Y" >>$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://raw.githubusercontent.com/MichMich/MagicMirror/develop/installers/dumpactivemodules.js > ~/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
|
||||||
|
|
||||||
|
if git fetch $remote; 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
|
||||||
|
|
@@ -11,6 +11,9 @@ var Utils = require(__dirname + "/utils.js");
|
|||||||
var defaultModules = require(__dirname + "/../modules/default/defaultmodules.js");
|
var defaultModules = require(__dirname + "/../modules/default/defaultmodules.js");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
|
||||||
|
// add timestamps in front of log messages
|
||||||
|
require('console-stamp')(console, 'HH:MM:ss.l');
|
||||||
|
|
||||||
// Get version number.
|
// Get version number.
|
||||||
global.version = JSON.parse(fs.readFileSync("package.json", "utf8")).version;
|
global.version = JSON.parse(fs.readFileSync("package.json", "utf8")).version;
|
||||||
console.log("Starting MagicMirror: v" + global.version);
|
console.log("Starting MagicMirror: v" + global.version);
|
||||||
|
@@ -203,7 +203,7 @@ var MM = (function() {
|
|||||||
*/
|
*/
|
||||||
var updateModuleContent = function(module, newHeader, newContent) {
|
var updateModuleContent = function(module, newHeader, newContent) {
|
||||||
var moduleWrapper = document.getElementById(module.identifier);
|
var moduleWrapper = document.getElementById(module.identifier);
|
||||||
if (moduleWrapper === null) return;
|
if (moduleWrapper === null) {return;}
|
||||||
var headerWrapper = moduleWrapper.getElementsByClassName("module-header");
|
var headerWrapper = moduleWrapper.getElementsByClassName("module-header");
|
||||||
var contentWrapper = moduleWrapper.getElementsByClassName("module-content");
|
var contentWrapper = moduleWrapper.getElementsByClassName("module-content");
|
||||||
|
|
||||||
|
@@ -41,26 +41,40 @@ Module.register("clock",{
|
|||||||
|
|
||||||
// Schedule update interval.
|
// Schedule update interval.
|
||||||
var self = this;
|
var self = this;
|
||||||
self.second = 0;
|
self.second = moment().second();
|
||||||
self.minute = 0;
|
self.minute = moment().minute();
|
||||||
self.lastDisplayedMinute = null;
|
|
||||||
setInterval(function() {
|
//Calculate how many ms should pass until next update depending on if seconds is displayed or not
|
||||||
if (self.config.displaySeconds || self.lastDisplayedMinute !== moment().minute()) {
|
var delayCalculator = function(reducedSeconds) {
|
||||||
|
if (self.config.displaySeconds) {
|
||||||
|
return 1000 - moment().milliseconds();
|
||||||
|
} else {
|
||||||
|
return ((60 - reducedSeconds) * 1000) - moment().milliseconds();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//A recursive timeout function instead of interval to avoid drifting
|
||||||
|
var notificationTimer = function() {
|
||||||
self.updateDom();
|
self.updateDom();
|
||||||
}
|
|
||||||
if (self.second === 59) {
|
//If seconds is displayed CLOCK_SECOND-notification should be sent (but not when CLOCK_MINUTE-notification is sent)
|
||||||
self.second = 0;
|
if (self.config.displaySeconds) {
|
||||||
if (self.minute === 59){
|
self.second = (self.second + 1) % 60;
|
||||||
self.minute = 0;
|
if (self.second !== 0) {
|
||||||
} else {
|
|
||||||
self.minute++;
|
|
||||||
}
|
|
||||||
self.sendNotification("CLOCK_MINUTE", self.minute);
|
|
||||||
} else {
|
|
||||||
self.second++;
|
|
||||||
self.sendNotification("CLOCK_SECOND", self.second);
|
self.sendNotification("CLOCK_SECOND", self.second);
|
||||||
|
setTimeout(notificationTimer, delayCalculator(0));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}, 1000);
|
}
|
||||||
|
|
||||||
|
//If minute changed or seconds isn't displayed send CLOCK_MINUTE-notification
|
||||||
|
self.minute = (self.minute + 1) % 60;
|
||||||
|
self.sendNotification("CLOCK_MINUTE", self.minute);
|
||||||
|
setTimeout(notificationTimer, delayCalculator(0));
|
||||||
|
};
|
||||||
|
|
||||||
|
//Set the initial timeout with the amount of seconds elapsed as reducedSeconds so it will trigger when the minute changes
|
||||||
|
setTimeout(notificationTimer, delayCalculator(self.second));
|
||||||
|
|
||||||
// Set locale.
|
// Set locale.
|
||||||
moment.locale(config.language);
|
moment.locale(config.language);
|
||||||
|
@@ -327,6 +327,11 @@ Module.register("newsfeed",{
|
|||||||
|
|
||||||
self.updateDom(self.config.animationSpeed);
|
self.updateDom(self.config.animationSpeed);
|
||||||
|
|
||||||
|
// Broadcast NewsFeed if needed
|
||||||
|
if (self.config.broadcastNewsFeeds) {
|
||||||
|
self.sendNotification("NEWS_FEED", {items: self.newsItems});
|
||||||
|
}
|
||||||
|
|
||||||
timer = setInterval(function() {
|
timer = setInterval(function() {
|
||||||
self.activeItem++;
|
self.activeItem++;
|
||||||
self.updateDom(self.config.animationSpeed);
|
self.updateDom(self.config.animationSpeed);
|
||||||
|
@@ -11,7 +11,7 @@ Module.register("updatenotification", {
|
|||||||
start: function () {
|
start: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
Log.log("Start updatenotification");
|
Log.log("Start updatenotification");
|
||||||
setInterval( () => { self.moduleList = {};self.updateDom(2) } , self.config.refreshInterval)
|
setInterval( () => { self.moduleList = {};self.updateDom(2); } , self.config.refreshInterval);
|
||||||
},
|
},
|
||||||
|
|
||||||
notificationReceived: function (notification, payload, sender) {
|
notificationReceived: function (notification, payload, sender) {
|
||||||
@@ -43,7 +43,7 @@ Module.register("updatenotification", {
|
|||||||
// if the module WAS in the list, but shouldn't be
|
// if the module WAS in the list, but shouldn't be
|
||||||
if(this.moduleList[payload.module] != undefined){
|
if(this.moduleList[payload.module] != undefined){
|
||||||
// remove it
|
// remove it
|
||||||
delete this.moduleList[payload.module]
|
delete this.moduleList[payload.module];
|
||||||
self.updateDom(2);
|
self.updateDom(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ Module.register("updatenotification", {
|
|||||||
if(this.suspended==false){
|
if(this.suspended==false){
|
||||||
// process the hash of module info found
|
// process the hash of module info found
|
||||||
for(key of Object.keys(this.moduleList)){
|
for(key of Object.keys(this.moduleList)){
|
||||||
let m= this.moduleList[key]
|
let m= this.moduleList[key];
|
||||||
|
|
||||||
var message = document.createElement("div");
|
var message = document.createElement("div");
|
||||||
message.className = "small bright";
|
message.className = "small bright";
|
||||||
|
@@ -32,7 +32,8 @@ WeatherProvider.register("darksky", {
|
|||||||
this.setCurrentWeather(currentWeather);
|
this.setCurrentWeather(currentWeather);
|
||||||
}).catch(function(request) {
|
}).catch(function(request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
});
|
})
|
||||||
|
.finally(() => this.updateAvailable())
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchWeatherForecast() {
|
fetchWeatherForecast() {
|
||||||
@@ -47,7 +48,8 @@ WeatherProvider.register("darksky", {
|
|||||||
this.setWeatherForecast(forecast);
|
this.setWeatherForecast(forecast);
|
||||||
}).catch(function(request) {
|
}).catch(function(request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
});
|
})
|
||||||
|
.finally(() => this.updateAvailable())
|
||||||
},
|
},
|
||||||
|
|
||||||
// Create a URL from the config and base URL.
|
// Create a URL from the config and base URL.
|
||||||
|
@@ -34,6 +34,7 @@ WeatherProvider.register("openweathermap", {
|
|||||||
.catch(function(request) {
|
.catch(function(request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
|
.finally(() => this.updateAvailable())
|
||||||
},
|
},
|
||||||
|
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
@@ -54,6 +55,7 @@ WeatherProvider.register("openweathermap", {
|
|||||||
.catch(function(request) {
|
.catch(function(request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
|
.finally(() => this.updateAvailable())
|
||||||
},
|
},
|
||||||
|
|
||||||
/** OpenWeatherMap Specific Methods - These are not part of the default provider methods */
|
/** OpenWeatherMap Specific Methods - These are not part of the default provider methods */
|
||||||
|
@@ -41,6 +41,7 @@ WeatherProvider.register("ukmetoffice", {
|
|||||||
.catch(function(request) {
|
.catch(function(request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
|
.finally(() => this.updateAvailable())
|
||||||
},
|
},
|
||||||
|
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
@@ -62,6 +63,7 @@ WeatherProvider.register("ukmetoffice", {
|
|||||||
.catch(function(request) {
|
.catch(function(request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
|
.finally(() => this.updateAvailable())
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@ WeatherProvider.register("weathergov", {
|
|||||||
.catch(function(request) {
|
.catch(function(request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
|
.finally(() => this.updateAvailable())
|
||||||
},
|
},
|
||||||
|
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
@@ -53,6 +54,7 @@ WeatherProvider.register("weathergov", {
|
|||||||
.catch(function(request) {
|
.catch(function(request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
|
.finally(() => this.updateAvailable())
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Weather.gov Specific Methods - These are not part of the default provider methods */
|
/** Weather.gov Specific Methods - These are not part of the default provider methods */
|
||||||
|
0
modules/default/weather/weather.js
Executable file → Normal file
0
modules/default/weather/weather.js
Executable file → Normal file
@@ -79,16 +79,12 @@ var WeatherProvider = Class.extend({
|
|||||||
setCurrentWeather: function(currentWeatherObject) {
|
setCurrentWeather: function(currentWeatherObject) {
|
||||||
// We should check here if we are passing a WeatherDay
|
// We should check here if we are passing a WeatherDay
|
||||||
this.currentWeatherObject = currentWeatherObject;
|
this.currentWeatherObject = currentWeatherObject;
|
||||||
|
|
||||||
this.updateAvailable();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set the weatherForecastArray and notify the delegate that new information is available.
|
// Set the weatherForecastArray and notify the delegate that new information is available.
|
||||||
setWeatherForecast: function(weatherForecastArray) {
|
setWeatherForecast: function(weatherForecastArray) {
|
||||||
// We should check here if we are passing a WeatherDay
|
// We should check here if we are passing a WeatherDay
|
||||||
this.weatherForecastArray = weatherForecastArray;
|
this.weatherForecastArray = weatherForecastArray;
|
||||||
|
|
||||||
this.updateAvailable();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set the fetched location name.
|
// Set the fetched location name.
|
||||||
|
@@ -180,9 +180,9 @@ Module.register("weatherforecast",{
|
|||||||
rainCell.innerHTML = "";
|
rainCell.innerHTML = "";
|
||||||
} else {
|
} else {
|
||||||
if(config.units !== "imperial") {
|
if(config.units !== "imperial") {
|
||||||
rainCell.innerHTML = parseFloat(forecast.rain).toFixed(1) + " mm";
|
rainCell.innerHTML = parseFloat(forecast.rain).toFixed(1).replace(".", this.config.decimalSymbol) + " mm";
|
||||||
} else {
|
} else {
|
||||||
rainCell.innerHTML = (parseFloat(forecast.rain) / 25.4).toFixed(2) + " in";
|
rainCell.innerHTML = (parseFloat(forecast.rain) / 25.4).toFixed(2).replace(".", this.config.decimalSymbol) + " in";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rainCell.className = "align-right bright rain";
|
rainCell.className = "align-right bright rain";
|
||||||
@@ -353,7 +353,7 @@ Module.register("weatherforecast",{
|
|||||||
icon: this.config.iconTable[forecast.weather[0].icon],
|
icon: this.config.iconTable[forecast.weather[0].icon],
|
||||||
maxTemp: this.roundValue(forecast.temp.max),
|
maxTemp: this.roundValue(forecast.temp.max),
|
||||||
minTemp: this.roundValue(forecast.temp.min),
|
minTemp: this.roundValue(forecast.temp.min),
|
||||||
rain: forecast.rain
|
rain: this.processRain(forecast, data.list)
|
||||||
};
|
};
|
||||||
|
|
||||||
this.forecast.push(forecastData);
|
this.forecast.push(forecastData);
|
||||||
@@ -434,5 +434,38 @@ Module.register("weatherforecast",{
|
|||||||
roundValue: function(temperature) {
|
roundValue: function(temperature) {
|
||||||
var decimals = this.config.roundTemp ? 0 : 1;
|
var decimals = this.config.roundTemp ? 0 : 1;
|
||||||
return parseFloat(temperature).toFixed(decimals);
|
return parseFloat(temperature).toFixed(decimals);
|
||||||
|
},
|
||||||
|
|
||||||
|
/* processRain(forecast, allForecasts)
|
||||||
|
* Calculates the amount of rain for a whole day even if long term forecasts isn't available for the appid.
|
||||||
|
*
|
||||||
|
* When using the the fallback endpoint forecasts are provided in 3h intervals and the rain-property is an object instead of number.
|
||||||
|
* That object has a property "3h" which contains the amount of rain since the previous forecast in the list.
|
||||||
|
* This code finds all forecasts that is for the same day and sums the amount of rain and returns that.
|
||||||
|
*/
|
||||||
|
processRain: function(forecast, allForecasts) {
|
||||||
|
//If the amount of rain actually is a number, return it
|
||||||
|
if (!isNaN(forecast.rain)) {
|
||||||
|
return forecast.rain;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Find all forecasts that is for the same day
|
||||||
|
var checkDateTime = (!!forecast.dt_txt) ? moment(forecast.dt_txt, "YYYY-MM-DD hh:mm:ss") : moment(forecast.dt, "X");
|
||||||
|
var daysForecasts = allForecasts.filter(function(item) {
|
||||||
|
var itemDateTime = (!!item.dt_txt) ? moment(item.dt_txt, "YYYY-MM-DD hh:mm:ss") : moment(item.dt, "X");
|
||||||
|
return itemDateTime.isSame(checkDateTime, "day") && item.rain instanceof Object;
|
||||||
|
});
|
||||||
|
|
||||||
|
//If no rain this day return undefined so it wont be displayed for this day
|
||||||
|
if (daysForecasts.length == 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Summarize all the rain from the matching days
|
||||||
|
return daysForecasts.map(function(item) {
|
||||||
|
return Object.values(item.rain)[0];
|
||||||
|
}).reduce(function(a, b) {
|
||||||
|
return a + b;
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
4131
package-lock.json
generated
4131
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "magicmirror",
|
"name": "magicmirror",
|
||||||
"version": "2.9.0-develop",
|
"version": "2.10.0-develop",
|
||||||
"description": "The open source modular smart mirror platform.",
|
"description": "The open source modular smart mirror platform.",
|
||||||
"main": "js/electron.js",
|
"main": "js/electron.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "sh run-start.sh",
|
"start": "./run-start.sh",
|
||||||
"install": "cd vendor && npm install",
|
"install": "cd vendor && npm install",
|
||||||
"install-fonts": "cd fonts && npm install",
|
"install-fonts": "cd fonts && npm install",
|
||||||
"postinstall": "sh installers/postinstall/postinstall.sh && npm run install-fonts",
|
"postinstall": "sh untrack-css.sh && sh installers/postinstall/postinstall.sh && npm run install-fonts",
|
||||||
"test": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests --recursive",
|
"test": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests --recursive",
|
||||||
"test:unit": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests/unit --recursive",
|
"test:unit": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests/unit --recursive",
|
||||||
"test:e2e": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests/e2e --recursive",
|
"test:e2e": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests/e2e --recursive",
|
||||||
@@ -55,14 +55,18 @@
|
|||||||
"stylelint-config-standard": "latest",
|
"stylelint-config-standard": "latest",
|
||||||
"time-grunt": "latest"
|
"time-grunt": "latest"
|
||||||
},
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"electron": "^3.0.13"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"colors": "^1.1.2",
|
"colors": "^1.1.2",
|
||||||
"electron": "^3.0.13",
|
"console-stamp": "^0.2.9",
|
||||||
"express": "^4.16.2",
|
"express": "^4.16.2",
|
||||||
"express-ipfilter": "^1.0.1",
|
"express-ipfilter": "^1.0.1",
|
||||||
"feedme": "latest",
|
"feedme": "latest",
|
||||||
"helmet": "^3.9.0",
|
"helmet": "^3.9.0",
|
||||||
"iconv-lite": "latest",
|
"iconv-lite": "latest",
|
||||||
|
"lodash": "^4.17.11",
|
||||||
"moment": "latest",
|
"moment": "latest",
|
||||||
"request": "^2.88.0",
|
"request": "^2.88.0",
|
||||||
"rrule": "^2.6.2",
|
"rrule": "^2.6.2",
|
||||||
|
62
run-start.sh
Normal file → Executable file
62
run-start.sh
Normal file → Executable file
@@ -1,4 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# use bash instead of sh
|
||||||
|
./untrack-css.sh
|
||||||
|
|
||||||
if [ -z "$DISPLAY" ]; then #If not set DISPLAY is SSH remote or tty
|
if [ -z "$DISPLAY" ]; then #If not set DISPLAY is SSH remote or tty
|
||||||
export DISPLAY=:0 # Set by default display
|
export DISPLAY=:0 # Set by default display
|
||||||
fi
|
fi
|
||||||
electron js/electron.js $1
|
# get the processor architecture
|
||||||
|
arch=$(uname -m)
|
||||||
|
# got the config option, if any
|
||||||
|
serveronly=$(grep -i serveronly: config/config.js | awk '{print tolower($2)}' | tr -d ,\"\')
|
||||||
|
# set default if not defined in config
|
||||||
|
serveronly="${serveronly:=false}"
|
||||||
|
# check for xwindows running
|
||||||
|
xorg=$(pgrep Xorg)
|
||||||
|
#check for macOS
|
||||||
|
mac=$(uname)
|
||||||
|
#
|
||||||
|
# if the user requested serveronly OR
|
||||||
|
# electron support for armv6l has been dropped OR
|
||||||
|
# system is in text mode
|
||||||
|
#
|
||||||
|
if [ "$serveronly." != "false." -o "$arch" == "armv6l" ] || [ "$xorg." == "." -a $mac != 'Darwin' ]; then
|
||||||
|
|
||||||
|
# if user explicitly configured to run server only (no ui local)
|
||||||
|
# OR there is no xwindows running, so no support for browser graphics
|
||||||
|
if [ "$serveronly." == "true." -o "$xorg." == "." ]; then
|
||||||
|
# start server mode,
|
||||||
|
node serveronly
|
||||||
|
else
|
||||||
|
# start the server in the background
|
||||||
|
# wait for server to be ready
|
||||||
|
# need bash for this
|
||||||
|
exec 3< <(node serveronly)
|
||||||
|
|
||||||
|
# Read the output of server line by line until one line 'point your browser'
|
||||||
|
while read line; do
|
||||||
|
case "$line" in
|
||||||
|
*point\ your\ browser*)
|
||||||
|
echo $line
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo $line
|
||||||
|
#sleep .25
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done <&3
|
||||||
|
|
||||||
|
# Close the file descriptor
|
||||||
|
exec 3<&-
|
||||||
|
|
||||||
|
# lets use chrome to display here now
|
||||||
|
# get the server port address from the ready message
|
||||||
|
port=$(echo $line | awk -F\: '{print $4}')
|
||||||
|
# start chromium
|
||||||
|
echo "Starting chromium browser now, have patience, it takes a minute"
|
||||||
|
chromium-browser -noerrdialogs -kiosk -start_maximized --disable-infobars --app=http://localhost:$port --ignore-certificate-errors-spki-list --ignore-ssl-errors --ignore-certificate-errors 2>/dev/null
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# we can use electron directly
|
||||||
|
`electron js/electron.js $1`;
|
||||||
|
fi
|
||||||
|
35
tests/configs/modules/weather/currentweather_default.js
Normal file
35
tests/configs/modules/weather/currentweather_default.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/* Magic Mirror Test config default weather
|
||||||
|
*
|
||||||
|
* By fewieden https://github.com/fewieden
|
||||||
|
*
|
||||||
|
* MIT Licensed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let config = {
|
||||||
|
port: 8080,
|
||||||
|
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
|
||||||
|
|
||||||
|
language: "en",
|
||||||
|
timeFormat: 12,
|
||||||
|
units: "metric",
|
||||||
|
electronOptions: {
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
module: "weather",
|
||||||
|
position: "bottom_bar",
|
||||||
|
config: {
|
||||||
|
location: "Munich",
|
||||||
|
apiKey: "fake key",
|
||||||
|
initialLoadDelay: 3000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
|
if (typeof module !== "undefined") {module.exports = config;}
|
40
tests/configs/modules/weather/currentweather_options.js
Normal file
40
tests/configs/modules/weather/currentweather_options.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/* Magic Mirror Test config default weather
|
||||||
|
*
|
||||||
|
* By fewieden https://github.com/fewieden
|
||||||
|
*
|
||||||
|
* MIT Licensed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let config = {
|
||||||
|
port: 8080,
|
||||||
|
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
|
||||||
|
|
||||||
|
language: "en",
|
||||||
|
timeFormat: 24,
|
||||||
|
units: "metric",
|
||||||
|
electronOptions: {
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
module: "weather",
|
||||||
|
position: "bottom_bar",
|
||||||
|
config: {
|
||||||
|
location: "Munich",
|
||||||
|
apiKey: "fake key",
|
||||||
|
initialLoadDelay: 3000,
|
||||||
|
useBeaufort: false,
|
||||||
|
showWindDirectionAsArrow: true,
|
||||||
|
showHumidity: true,
|
||||||
|
roundTemp: true,
|
||||||
|
degreeLabel: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
|
if (typeof module !== "undefined") {module.exports = config;}
|
37
tests/configs/modules/weather/currentweather_units.js
Normal file
37
tests/configs/modules/weather/currentweather_units.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/* Magic Mirror Test config default weather
|
||||||
|
*
|
||||||
|
* By fewieden https://github.com/fewieden
|
||||||
|
*
|
||||||
|
* MIT Licensed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let config = {
|
||||||
|
port: 8080,
|
||||||
|
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
|
||||||
|
|
||||||
|
language: "en",
|
||||||
|
timeFormat: 24,
|
||||||
|
units: "imperial",
|
||||||
|
electronOptions: {
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
module: "weather",
|
||||||
|
position: "bottom_bar",
|
||||||
|
config: {
|
||||||
|
location: "Munich",
|
||||||
|
apiKey: "fake key",
|
||||||
|
initialLoadDelay: 3000,
|
||||||
|
decimalSymbol: ",",
|
||||||
|
showHumidity: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
|
if (typeof module !== "undefined") {module.exports = config;}
|
37
tests/configs/modules/weather/forecastweather_default.js
Normal file
37
tests/configs/modules/weather/forecastweather_default.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/* Magic Mirror Test config default weather
|
||||||
|
*
|
||||||
|
* By fewieden https://github.com/fewieden
|
||||||
|
*
|
||||||
|
* MIT Licensed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let config = {
|
||||||
|
port: 8080,
|
||||||
|
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
|
||||||
|
|
||||||
|
language: "en",
|
||||||
|
timeFormat: 12,
|
||||||
|
units: "metric",
|
||||||
|
electronOptions: {
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
module: "weather",
|
||||||
|
position: "bottom_bar",
|
||||||
|
config: {
|
||||||
|
type: "forecast",
|
||||||
|
location: "Munich",
|
||||||
|
apiKey: "fake key",
|
||||||
|
weatherEndpoint: "/forecast/daily",
|
||||||
|
initialLoadDelay: 3000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
|
if (typeof module !== "undefined") {module.exports = config;}
|
40
tests/configs/modules/weather/forecastweather_options.js
Normal file
40
tests/configs/modules/weather/forecastweather_options.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/* Magic Mirror Test config default weather
|
||||||
|
*
|
||||||
|
* By fewieden https://github.com/fewieden
|
||||||
|
*
|
||||||
|
* MIT Licensed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let config = {
|
||||||
|
port: 8080,
|
||||||
|
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
|
||||||
|
|
||||||
|
language: "en",
|
||||||
|
timeFormat: 12,
|
||||||
|
units: "metric",
|
||||||
|
electronOptions: {
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
module: "weather",
|
||||||
|
position: "bottom_bar",
|
||||||
|
config: {
|
||||||
|
type: "forecast",
|
||||||
|
location: "Munich",
|
||||||
|
apiKey: "fake key",
|
||||||
|
weatherEndpoint: "/forecast/daily",
|
||||||
|
initialLoadDelay: 3000,
|
||||||
|
showPrecipitationAmount: true,
|
||||||
|
colored: true,
|
||||||
|
tableClass: "myTableClass"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
|
if (typeof module !== "undefined") {module.exports = config;}
|
4
tests/e2e/modules/mocks/index.js
Normal file
4
tests/e2e/modules/mocks/index.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
const generateWeather = require("./weather_current");
|
||||||
|
const generateWeatherForecast = require("./weather_forecast");
|
||||||
|
|
||||||
|
module.exports = {generateWeather, generateWeatherForecast};
|
54
tests/e2e/modules/mocks/weather_current.js
Normal file
54
tests/e2e/modules/mocks/weather_current.js
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
function generateWeather(extendedData = {}) {
|
||||||
|
return JSON.stringify(_.merge({}, {
|
||||||
|
coord:{
|
||||||
|
lon: 11.58,
|
||||||
|
lat: 48.14
|
||||||
|
},
|
||||||
|
weather:[
|
||||||
|
{
|
||||||
|
id: 615,
|
||||||
|
main: "Snow",
|
||||||
|
description: "light rain and snow",
|
||||||
|
icon: "13d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 500,
|
||||||
|
main: "Rain",
|
||||||
|
description: "light rain",
|
||||||
|
icon: "10d"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
base: "stations",
|
||||||
|
main:{
|
||||||
|
temp: 1.49,
|
||||||
|
pressure: 1005,
|
||||||
|
humidity: 93.7,
|
||||||
|
temp_min: 1,
|
||||||
|
temp_max: 2
|
||||||
|
},
|
||||||
|
visibility: 7000,
|
||||||
|
wind:{
|
||||||
|
speed: 11.8,
|
||||||
|
deg: 250
|
||||||
|
},
|
||||||
|
clouds:{
|
||||||
|
all: 75
|
||||||
|
},
|
||||||
|
dt: 1547387400,
|
||||||
|
sys:{
|
||||||
|
type: 1,
|
||||||
|
id: 1267,
|
||||||
|
message: 0.0031,
|
||||||
|
country: "DE",
|
||||||
|
sunrise: 1547362817,
|
||||||
|
sunset: 1547394301
|
||||||
|
},
|
||||||
|
id: 2867714,
|
||||||
|
name: "Munich",
|
||||||
|
cod: 200
|
||||||
|
}, extendedData));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = generateWeather;
|
97
tests/e2e/modules/mocks/weather_forecast.js
Normal file
97
tests/e2e/modules/mocks/weather_forecast.js
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
function generateWeatherForecast(extendedData = {}) {
|
||||||
|
return JSON.stringify(_.merge({}, {
|
||||||
|
"city": {
|
||||||
|
"id": 2867714,
|
||||||
|
"name": "Munich",
|
||||||
|
"coord": {"lon": 11.5754, "lat": 48.1371},
|
||||||
|
"country": "DE",
|
||||||
|
"population": 1260391,
|
||||||
|
"timezone": 7200
|
||||||
|
},
|
||||||
|
"cod": "200",
|
||||||
|
"message": 0.9653487,
|
||||||
|
"cnt": 7,
|
||||||
|
"list": [{
|
||||||
|
"dt": 1568372400,
|
||||||
|
"sunrise": 1568350044,
|
||||||
|
"sunset": 1568395948,
|
||||||
|
"temp": {"day": 24.44, "min": 15.35, "max": 24.44, "night": 15.35, "eve": 18, "morn": 23.03},
|
||||||
|
"pressure": 1031.65,
|
||||||
|
"humidity": 70,
|
||||||
|
"weather": [{"id": 801, "main": "Clouds", "description": "few clouds", "icon": "02d"}],
|
||||||
|
"speed": 3.35,
|
||||||
|
"deg": 314,
|
||||||
|
"clouds": 21
|
||||||
|
}, {
|
||||||
|
"dt": 1568458800,
|
||||||
|
"sunrise": 1568436525,
|
||||||
|
"sunset": 1568482223,
|
||||||
|
"temp": {"day": 20.81, "min": 13.56, "max": 21.02, "night": 13.56, "eve": 16.6, "morn": 15.88},
|
||||||
|
"pressure": 1028.81,
|
||||||
|
"humidity": 72,
|
||||||
|
"weather": [{"id": 500, "main": "Rain", "description": "light rain", "icon": "10d"}],
|
||||||
|
"speed": 2.21,
|
||||||
|
"deg": 81,
|
||||||
|
"clouds": 100
|
||||||
|
}, {
|
||||||
|
"dt": 1568545200,
|
||||||
|
"sunrise": 1568523007,
|
||||||
|
"sunset": 1568568497,
|
||||||
|
"temp": {"day": 22.65, "min": 13.76, "max": 22.88, "night": 15.27, "eve": 17.45, "morn": 13.76},
|
||||||
|
"pressure": 1023.75,
|
||||||
|
"humidity": 64,
|
||||||
|
"weather": [{"id": 800, "main": "Clear", "description": "sky is clear", "icon": "01d"}],
|
||||||
|
"speed": 1.15,
|
||||||
|
"deg": 7,
|
||||||
|
"clouds": 0
|
||||||
|
}, {
|
||||||
|
"dt": 1568631600,
|
||||||
|
"sunrise": 1568609489,
|
||||||
|
"sunset": 1568654771,
|
||||||
|
"temp": {"day": 23.45, "min": 13.95, "max": 23.45, "night": 13.95, "eve": 17.75, "morn": 15.21},
|
||||||
|
"pressure": 1020.41,
|
||||||
|
"humidity": 64,
|
||||||
|
"weather": [{"id": 800, "main": "Clear", "description": "sky is clear", "icon": "01d"}],
|
||||||
|
"speed": 3.07,
|
||||||
|
"deg": 298,
|
||||||
|
"clouds": 7
|
||||||
|
}, {
|
||||||
|
"dt": 1568718000,
|
||||||
|
"sunrise": 1568695970,
|
||||||
|
"sunset": 1568741045,
|
||||||
|
"temp": {"day": 20.55, "min": 10.95, "max": 20.55, "night": 10.95, "eve": 14.82, "morn": 13.24},
|
||||||
|
"pressure": 1019.4,
|
||||||
|
"humidity": 66,
|
||||||
|
"weather": [{"id": 800, "main": "Clear", "description": "sky is clear", "icon": "01d"}],
|
||||||
|
"speed": 2.8,
|
||||||
|
"deg": 333,
|
||||||
|
"clouds": 2
|
||||||
|
}, {
|
||||||
|
"dt": 1568804400,
|
||||||
|
"sunrise": 1568782452,
|
||||||
|
"sunset": 1568827319,
|
||||||
|
"temp": {"day": 18.15, "min": 7.75, "max": 18.15, "night": 7.75, "eve": 12.45, "morn": 9.41},
|
||||||
|
"pressure": 1017.56,
|
||||||
|
"humidity": 52,
|
||||||
|
"weather": [{"id": 800, "main": "Clear", "description": "sky is clear", "icon": "01d"}],
|
||||||
|
"speed": 2.92,
|
||||||
|
"deg": 34,
|
||||||
|
"clouds": 0
|
||||||
|
}, {
|
||||||
|
"dt": 1568890800,
|
||||||
|
"sunrise": 1568868934,
|
||||||
|
"sunset": 1568913593,
|
||||||
|
"temp": {"day": 14.85, "min": 5.56, "max": 15.05, "night": 5.56, "eve": 9.56, "morn": 6.25},
|
||||||
|
"pressure": 1022.7,
|
||||||
|
"humidity": 59,
|
||||||
|
"weather": [{"id": 800, "main": "Clear", "description": "sky is clear", "icon": "01d"}],
|
||||||
|
"speed": 2.89,
|
||||||
|
"deg": 51,
|
||||||
|
"clouds": 1
|
||||||
|
}]
|
||||||
|
}, extendedData));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = generateWeatherForecast;
|
270
tests/e2e/modules/weather_spec.js
Normal file
270
tests/e2e/modules/weather_spec.js
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
const expect = require("chai").expect;
|
||||||
|
const fs = require("fs");
|
||||||
|
const moment = require("moment");
|
||||||
|
const path = require("path");
|
||||||
|
const wdajaxstub = require("webdriverajaxstub");
|
||||||
|
|
||||||
|
const helpers = require("../global-setup");
|
||||||
|
|
||||||
|
const {generateWeather, generateWeatherForecast} = require("./mocks");
|
||||||
|
|
||||||
|
const wait = () => new Promise(res => setTimeout(res, 3000));
|
||||||
|
|
||||||
|
describe("Weather module", function() {
|
||||||
|
let app;
|
||||||
|
|
||||||
|
helpers.setupTimeout(this);
|
||||||
|
|
||||||
|
async function setup(responses) {
|
||||||
|
app = await helpers.startApplication({
|
||||||
|
args: ["js/electron.js"]
|
||||||
|
});
|
||||||
|
|
||||||
|
wdajaxstub.init(app.client, responses);
|
||||||
|
|
||||||
|
app.client.setupStub();
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
return helpers.stopApplication(app);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Current weather", function() {
|
||||||
|
let template;
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
template = fs.readFileSync(path.join(__dirname, "..", "..", "..", "modules", "default", "weather", "current.njk"), "utf8");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Default configuration", function() {
|
||||||
|
before(function() {
|
||||||
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/weather/currentweather_default.js";
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render wind speed and wind direction", async function() {
|
||||||
|
const weather = generateWeather();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
return app.client.waitUntilTextExists(".weather .normal.medium span:nth-child(2)", "6 WSW", 10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render sunrise", async function() {
|
||||||
|
const sunrise = moment().startOf("day").unix();
|
||||||
|
const sunset = moment().startOf("day").unix();
|
||||||
|
|
||||||
|
const weather = generateWeather({sys: {sunrise, sunset}});
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
await app.client.waitForExist(".weather .normal.medium span.wi.dimmed.wi-sunrise", 10000);
|
||||||
|
|
||||||
|
return app.client.waitUntilTextExists(".weather .normal.medium span:nth-child(4)", "12:00 am", 10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render sunset", async function() {
|
||||||
|
const sunrise = moment().startOf("day").unix();
|
||||||
|
const sunset = moment().endOf("day").unix();
|
||||||
|
|
||||||
|
const weather = generateWeather({sys: {sunrise, sunset}});
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
await app.client.waitForExist(".weather .normal.medium span.wi.dimmed.wi-sunset", 10000);
|
||||||
|
|
||||||
|
return app.client.waitUntilTextExists(".weather .normal.medium span:nth-child(4)", "11:59 pm", 10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render temperature with icon", async function() {
|
||||||
|
const weather = generateWeather();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
await app.client.waitForExist(".weather .large.light span.wi.weathericon.wi-snow", 10000);
|
||||||
|
|
||||||
|
return app.client.waitUntilTextExists(".weather .large.light span.bright", "1.5°", 10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render feels like temperature", async function() {
|
||||||
|
const weather = generateWeather();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
return app.client.waitUntilTextExists(".weather .normal.medium span.dimmed", "Feels like -5.6°", 10000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Configuration Options", function() {
|
||||||
|
before(function() {
|
||||||
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/weather/currentweather_options.js";
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render useBeaufort = false", async function() {
|
||||||
|
const weather = generateWeather();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
return app.client.waitUntilTextExists(".weather .normal.medium span:nth-child(2)", "12", 10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render showWindDirectionAsArrow = true", async function() {
|
||||||
|
const weather = generateWeather();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
await app.client.waitForExist(".weather .normal.medium sup i.fa-long-arrow-up", 10000);
|
||||||
|
const element = await app.client.getHTML(".weather .normal.medium sup i.fa-long-arrow-up");
|
||||||
|
|
||||||
|
expect(element).to.include("transform:rotate(250deg);");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render showHumidity = true", async function() {
|
||||||
|
const weather = generateWeather();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
await app.client.waitUntilTextExists(".weather .normal.medium span:nth-child(3)", "93", 10000);
|
||||||
|
return app.client.waitForExist(".weather .normal.medium sup i.wi-humidity", 10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render degreeLabel = true", async function() {
|
||||||
|
const weather = generateWeather();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
await app.client.waitUntilTextExists(".weather .large.light span.bright", "1°C", 10000);
|
||||||
|
|
||||||
|
return app.client.waitUntilTextExists(".weather .normal.medium span.dimmed", "Feels like -6°C", 10000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Current weather units", function() {
|
||||||
|
before(function() {
|
||||||
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/weather/currentweather_units.js";
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render imperial units", async function() {
|
||||||
|
const weather = generateWeather({
|
||||||
|
main:{
|
||||||
|
temp: 1.49 * 9 / 5 + 32,
|
||||||
|
temp_min: 1 * 9 / 5 + 32,
|
||||||
|
temp_max: 2 * 9 / 5 + 32
|
||||||
|
},
|
||||||
|
wind:{
|
||||||
|
speed: 11.8 * 2.23694
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
await app.client.waitUntilTextExists(".weather .normal.medium span:nth-child(2)", "6 WSW", 10000);
|
||||||
|
await app.client.waitUntilTextExists(".weather .large.light span.bright", "34,7°", 10000);
|
||||||
|
return app.client.waitUntilTextExists(".weather .normal.medium span.dimmed", "22,0°", 10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render decimalSymbol = ','", async function() {
|
||||||
|
const weather = generateWeather({
|
||||||
|
main:{
|
||||||
|
temp: 1.49 * 9 / 5 + 32,
|
||||||
|
temp_min: 1 * 9 / 5 + 32,
|
||||||
|
temp_max: 2 * 9 / 5 + 32
|
||||||
|
},
|
||||||
|
wind:{
|
||||||
|
speed: 11.8 * 2.23694
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
await app.client.waitUntilTextExists(".weather .normal.medium span:nth-child(3)", "93,7", 10000);
|
||||||
|
await app.client.waitUntilTextExists(".weather .large.light span.bright", "34,7°", 10000);
|
||||||
|
return app.client.waitUntilTextExists(".weather .normal.medium span.dimmed", "22,0°", 10000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Weather Forecast", function() {
|
||||||
|
let template;
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
template = fs.readFileSync(path.join(__dirname, "..", "..", "..", "modules", "default", "weather", "forecast.njk"), "utf8");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Default configuration", function() {
|
||||||
|
before(function() {
|
||||||
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/weather/forecastweather_default.js";
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render days", async function() {
|
||||||
|
const weather = generateWeatherForecast();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
const days = ["Fri", "Sat", "Sun", "Mon", "Tue"];
|
||||||
|
|
||||||
|
for (const [index, day] of days.entries()) {
|
||||||
|
await app.client.waitUntilTextExists(`.weather table.small tr:nth-child(${index + 1}) td:nth-child(1)`, day, 10000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render icons", async function() {
|
||||||
|
const weather = generateWeatherForecast();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
const icons = ["day-cloudy", "rain", "day-sunny", "day-sunny", "day-sunny"];
|
||||||
|
|
||||||
|
for (const [index, icon] of icons.entries()) {
|
||||||
|
await app.client.waitForExist(`.weather table.small tr:nth-child(${index + 1}) td:nth-child(2) span.wi-${icon}`, 10000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render max temperatures", async function() {
|
||||||
|
const weather = generateWeatherForecast();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
const temperatures = ["24.4°", "21.0°", "22.9°", "23.4°", "20.6°"];
|
||||||
|
|
||||||
|
for (const [index, temp] of temperatures.entries()) {
|
||||||
|
await app.client.waitUntilTextExists(`.weather table.small tr:nth-child(${index + 1}) td:nth-child(3)`, temp, 10000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render min temperatures", async function() {
|
||||||
|
const weather = generateWeatherForecast();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
const temperatures = ["15.3°", "13.6°", "13.8°", "13.9°", "10.9°"];
|
||||||
|
|
||||||
|
for (const [index, temp] of temperatures.entries()) {
|
||||||
|
await app.client.waitUntilTextExists(`.weather table.small tr:nth-child(${index + 1}) td:nth-child(4)`, temp, 10000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render fading of rows", async function() {
|
||||||
|
const weather = generateWeatherForecast();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
const opacities = [1, 1, 0.8, 0.5333333333333333, 0.2666666666666667];
|
||||||
|
|
||||||
|
await app.client.waitForExist('.weather table.small', 10000);
|
||||||
|
|
||||||
|
for (const [index, opacity] of opacities.entries()) {
|
||||||
|
const html = await app.client.getHTML(`.weather table.small tr:nth-child(${index + 1})`);
|
||||||
|
expect(html).to.includes(`<tr style="opacity: ${opacity};">`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Configuration Options", function() {
|
||||||
|
before(function() {
|
||||||
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/weather/forecastweather_options.js";
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render custom table class", async function() {
|
||||||
|
const weather = generateWeatherForecast();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
await app.client.waitForExist(`.weather table.myTableClass`, 10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render colored rows", async function() {
|
||||||
|
const weather = generateWeatherForecast();
|
||||||
|
await setup([weather, template]);
|
||||||
|
|
||||||
|
await app.client.waitForExist(`.weather table.myTableClass`, 10000);
|
||||||
|
|
||||||
|
const rows = await app.client.$$('.weather table.myTableClass tr.colored');
|
||||||
|
|
||||||
|
expect(rows.length).to.be.equal(5);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -6,11 +6,10 @@ const describe = global.describe;
|
|||||||
const it = global.it;
|
const it = global.it;
|
||||||
const before = global.before;
|
const before = global.before;
|
||||||
const after = global.after;
|
const after = global.after;
|
||||||
|
const mlog = require("mocha-logger");
|
||||||
|
|
||||||
describe("Vendors", function () {
|
describe("Vendors", function () {
|
||||||
|
|
||||||
return; // Test still getting failed in Travis
|
|
||||||
|
|
||||||
helpers.setupTimeout(this);
|
helpers.setupTimeout(this);
|
||||||
|
|
||||||
var app = null;
|
var app = null;
|
||||||
@@ -40,5 +39,17 @@ describe("Vendors", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Object.keys(vendors).forEach(vendor => {
|
||||||
|
it(`should return 404 HTTP code for vendor https://localhost/"${vendor}"`, function() {
|
||||||
|
urlVendor = "http://localhost:8080/" + vendors[vendor];
|
||||||
|
request.get(urlVendor, function (err, res, body) {
|
||||||
|
if (!err)
|
||||||
|
expect(res.statusCode).to.equal(404);
|
||||||
|
else
|
||||||
|
mlog.pending(`There error vendor 404 test ${err}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
33
tests/node_modules/webdriverajaxstub/index.js
generated
vendored
Normal file
33
tests/node_modules/webdriverajaxstub/index.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
function plugin (wdInstance, requests) {
|
||||||
|
if (typeof wdInstance.addCommand !== "function") {
|
||||||
|
throw new Error("You can't use WebdriverAjaxStub with this version of WebdriverIO");
|
||||||
|
}
|
||||||
|
|
||||||
|
function stub(requests, done) {
|
||||||
|
window.XMLHttpRequest = function () {
|
||||||
|
this.open = function (method, url) {
|
||||||
|
this.method = method;
|
||||||
|
this.url = url;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.send = function () {
|
||||||
|
this.status = 200;
|
||||||
|
this.readyState = 4;
|
||||||
|
const response = requests.shift() || [];
|
||||||
|
this.response = response;
|
||||||
|
this.responseText = response;
|
||||||
|
this.onreadystatechange();
|
||||||
|
};
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
|
||||||
|
wdInstance.addCommand("setupStub", function() {
|
||||||
|
return wdInstance.executeAsync(stub, requests);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.init = plugin;
|
0
translations/en.json
Executable file → Normal file
0
translations/en.json
Executable file → Normal file
@@ -31,5 +31,6 @@
|
|||||||
"UPDATE_INFO_SINGLE": "Tu actual instalación está {COMMIT_COUNT} commit cambios detrás de la rama {BRANCH_NAME}.",
|
"UPDATE_INFO_SINGLE": "Tu actual instalación está {COMMIT_COUNT} commit cambios detrás de la rama {BRANCH_NAME}.",
|
||||||
"UPDATE_INFO_MULTIPLE": "Tu actual instalación está {COMMIT_COUNT} commits cambios detrás de la rama {BRANCH_NAME}.",
|
"UPDATE_INFO_MULTIPLE": "Tu actual instalación está {COMMIT_COUNT} commits cambios detrás de la rama {BRANCH_NAME}.",
|
||||||
|
|
||||||
"FEELS": "Sensación térmica de"
|
"FEELS": "Sensación térmica de",
|
||||||
|
"PRECIP": "Precipitación"
|
||||||
}
|
}
|
||||||
|
33
translations/ms-my.json
Normal file
33
translations/ms-my.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"LOADING": "Tunggu Sebentar …",
|
||||||
|
|
||||||
|
"TODAY": "Hari ini",
|
||||||
|
"TOMORROW": "Esok",
|
||||||
|
"DAYAFTERTOMORROW": "Lusa",
|
||||||
|
"RUNNING": "Berakhir dalam",
|
||||||
|
"EMPTY": "Tidak ada agenda",
|
||||||
|
|
||||||
|
"WEEK": "Minggu ke-{weekNumber}",
|
||||||
|
|
||||||
|
"N": "U",
|
||||||
|
"NNE": "UUT",
|
||||||
|
"NE": "TL",
|
||||||
|
"ENE": "TTL",
|
||||||
|
"E": "T",
|
||||||
|
"ESE": "TT",
|
||||||
|
"SE": "T",
|
||||||
|
"SSE": "ST",
|
||||||
|
"S": "S",
|
||||||
|
"SSW": "SBD",
|
||||||
|
"SW": "BD",
|
||||||
|
"WSW": "BBD",
|
||||||
|
"W": "B",
|
||||||
|
"WNW": "BBL",
|
||||||
|
"NW": "BL",
|
||||||
|
"NNW": "UBL",
|
||||||
|
|
||||||
|
"UPDATE_NOTIFICATION": "MagicMirror² mempunyai update terkini.",
|
||||||
|
"UPDATE_NOTIFICATION_MODULE": "Modul {MODULE_NAME} mempunyai update terkini.",
|
||||||
|
"UPDATE_INFO_SINGLE": "Pemasangan MagicMirror² ini mempunyai {COMMIT_COUNT} commit terkebelakang dari branch {BRANCH_NAME}.",
|
||||||
|
"UPDATE_INFO_MULTIPLE": "Pemasangan MagicMirror² ini mempunyai {COMMIT_COUNT} commit terkebelakang dari branch {BRANCH_NAME}."
|
||||||
|
}
|
@@ -40,7 +40,8 @@ var translations = {
|
|||||||
"cs" : "translations/cs.json", // Czech
|
"cs" : "translations/cs.json", // Czech
|
||||||
"hr" : "translations/hr.json", // Croatian
|
"hr" : "translations/hr.json", // Croatian
|
||||||
"sk" : "translations/sk.json", // Slovak
|
"sk" : "translations/sk.json", // Slovak
|
||||||
"tlh" : "translations/tlh.json" // Klingon
|
"tlh" : "translations/tlh.json", // Klingon
|
||||||
|
"ms-my" : "translations/ms-my.json" // Malay
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof module !== "undefined") {module.exports = translations;}
|
if (typeof module !== "undefined") {module.exports = translations;}
|
||||||
|
11
untrack-css.sh
Executable file
11
untrack-css.sh
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
# Long history here
|
||||||
|
# https://github.com/MichMich/MagicMirror/pull/1540
|
||||||
|
STATUS_CUSTOM_CSS=$(git ls-files -v css/custom.css| awk '{print $1}')
|
||||||
|
|
||||||
|
if [ "$STATUS_CUSTOM_CSS" = "H" ]; then
|
||||||
|
echo "We'll remove from the repository the css/custom.css"
|
||||||
|
echo "This script apply git update-index --skip-worktree css/custom.css"
|
||||||
|
git update-index --skip-worktree css/custom.css
|
||||||
|
git rm --cached css/custom.css
|
||||||
|
fi
|
||||||
|
|
2
vendor/package-lock.json
generated
vendored
2
vendor/package-lock.json
generated
vendored
@@ -5,7 +5,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": {
|
"@fortawesome/fontawesome-free": {
|
||||||
"version": "5.6.3",
|
"version": "5.6.3",
|
||||||
"resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.6.3.tgz",
|
||||||
"integrity": "sha512-s5PLdI9NYgjBvfrv6rhirPHlAHWx+Sfo/IjsAeiXYfmemC/GSjwsyz1wLnGPazbLPXWfk62ks980o9AmsxYUEQ=="
|
"integrity": "sha512-s5PLdI9NYgjBvfrv6rhirPHlAHWx+Sfo/IjsAeiXYfmemC/GSjwsyz1wLnGPazbLPXWfk62ks980o9AmsxYUEQ=="
|
||||||
},
|
},
|
||||||
"a-sync-waterfall": {
|
"a-sync-waterfall": {
|
||||||
|
Reference in New Issue
Block a user