├── MMM-OralB.css
├── CHANGELOG.md
├── translations
├── en.json
├── es.json
└── de.json
├── .gitignore
├── package.json
├── findBrushId.js
├── LICENCE
├── README.md
├── node_helper.js
└── MMM-OralB.js
/MMM-OralB.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [1.0.0] - Initial Release
2 |
3 | First public release
4 |
--------------------------------------------------------------------------------
/translations/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "searching...": "searching...",
3 | "Time": "Time"
4 | }
5 |
--------------------------------------------------------------------------------
/translations/es.json:
--------------------------------------------------------------------------------
1 | {
2 | "searching...": "searching...",
3 | "Time": "Time"
4 | }
5 |
--------------------------------------------------------------------------------
/translations/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "searching...": "suche...",
3 | "Time": "Zeit: ",
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # https://git-scm.com/docs/gitignore
2 | # https://help.github.com/articles/ignoring-files
3 | # Example .gitignore files: https://github.com/github/gitignore
4 | /node_modules/
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mmm-oralb",
3 | "version": "1.0.0",
4 | "description": "OralB Toothbrush integration for the Magic Mirror",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/SvenSommer/MMM-OralB"
8 | },
9 | "keywords": [
10 | "magic mirror",
11 | "smart mirror",
12 | "OralB",
13 | "module",
14 | "Toothbrush"
15 | ],
16 | "author": "Sven Sommer",
17 | "license": "MIT",
18 | "bugs": {
19 | "url": "https://github.com/SvenSommer/MMM-OralB/issues"
20 | },
21 | "dependencies": {
22 | "noble": "latest"
23 | },
24 | "homepage": "https://github.com/SvenSommer/MMM-OralB#readme"
25 | }
26 |
--------------------------------------------------------------------------------
/findBrushId.js:
--------------------------------------------------------------------------------
1 | var async = require('async');
2 | var noble = require('noble');
3 |
4 | var OralB_manufacturerData = 'dc00010205030000000101';
5 | process.env['NOBLE_HCI_DEVICE_ID'] = 0
6 |
7 | noble.on('stateChange', function(state) {
8 | console.log('changed state to:' + noble.state);
9 | if (state === 'poweredOn') {
10 | noble.startScanning();
11 | } else {
12 | console.log('changed state to off: ' + noble.state);
13 | noble.stopScanning();
14 | }
15 | });
16 |
17 |
18 | console.log('Searching for OralB Toothbrushes with manufacturerData: "' + OralB_manufacturerData +'"...');
19 |
20 | noble.on('discover', function(peripheral) {
21 | var advertisement = peripheral.advertisement;
22 | if (advertisement.manufacturerData) {
23 | if (advertisement.manufacturerData.toString('hex') === OralB_manufacturerData) {
24 | console.log('Found OralB Tootbrush with ID: ' + peripheral.id);
25 | noble.stopScanning();
26 | }
27 | }
28 |
29 | });
30 |
--------------------------------------------------------------------------------
/LICENCE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Lukas Scheffler
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MMM-OralB
2 | This a module for the [MagicMirror²](https://github.com/MichMich/MagicMirror). It tries to discover a OralB Toothbrush and starts a timer while its connected.
3 |
4 | ## Preview
5 |
6 | ## Installation
7 |
8 |
9 | 1. Enter module-directory: `cd ~/MagicMirror/modules`
10 | 2. Clone repository : `git clone https://github.com/SvenSommer/MMM-OralB`
11 | 3. Enter new directory: `cd ~/MagicMirror/modules/MMM-OralB`
12 | 4. Install dependencies: `sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev`
13 | 5. Install noble module: `npm install noble`
14 | 6. Rebuild package to avoid version conflict: `sudo npm rebuild --runtime=electron --target=1.4.6 --disturl=https://atom.io/download/atom-shell --abi=50 `
15 |
16 | ## Integration
17 |
18 | Add module information to your `~/MagicMirror/config/config.js`.
19 |
20 | Here is an example of an entry in `config.js`:
21 | ```
22 | {
23 | module: 'MMM-OralB',
24 | position: 'bottom_left',
25 | },
26 | ```
27 |
28 | ## Special Thanks
29 | - [Michael Teeuw](https://github.com/MichMich) for creating the genius [MagicMirror²](https://github.com/MichMich/MagicMirror/tree/develop) project that made this module possible.
30 |
--------------------------------------------------------------------------------
/node_helper.js:
--------------------------------------------------------------------------------
1 | /* Magic Mirror
2 | * Module: MMM-OralB
3 | *
4 | * By SvenSommer https://github.com/SvenSommer
5 | * MIT Licensed.
6 | */
7 | var NodeHelper = require('node_helper');
8 | //var noble = require('noble');
9 |
10 | module.exports = NodeHelper.create({
11 |
12 | // Override socketNotificationReceived method.
13 |
14 | /* socketNotificationReceived(notification, payload)
15 | * This method is called when a socket notification arrives.
16 | *
17 | * argument notification string - The identifier of the noitication.
18 | * argument payload mixed - The payload of the notification.
19 | */
20 | socketNotificationReceived: function(notification, payload) {
21 | var self = this;
22 | this.config = payload;
23 | if (self.config.debug) {
24 | console.log(notification, "received by node_helper.js received");
25 | }
26 | if (notification === "MMM-OralB-GET_DATA") {
27 | this.getDataFromBrush(function(data){
28 | self.sendNotification_DISPLAY_DATA(data);
29 | });
30 | }
31 | },
32 |
33 | // Example function send notification test
34 | sendNotification_DISPLAY_DATA: function(payload) {
35 | this.sendSocketNotification("MMM-OralB-DISPLAY_DATA", payload);
36 | },
37 |
38 | getDataFromBrush: function(callback) {
39 | var self = this;
40 | var d = new Date();
41 | var toothbrushDataObject= {
42 | 'brushingTime': "00:" + ("0" + d.getSeconds()).slice(-2) ,
43 | 'sector': 4}
44 |
45 | callback(toothbrushDataObject);
46 | },
47 | });
48 |
--------------------------------------------------------------------------------
/MMM-OralB.js:
--------------------------------------------------------------------------------
1 | /* global Module */
2 |
3 | /* Magic Mirror
4 | * Module: MMM-OralB
5 | *
6 | * By SvenSommer
7 | * MIT Licensed.
8 | */
9 |
10 | Module.register("MMM-OralB",{
11 |
12 | // Default module config.
13 | defaults: {
14 | updateInterval: 1000,
15 | debug: true
16 | },
17 |
18 | requiresVersion: "2.1.0", // Required version of MagicMirror
19 |
20 | start: function() {
21 | var self = this;
22 | var dataRequest = null;
23 | var dataNotification = null;
24 |
25 | //Flag for check if module is loaded
26 | this.loaded = false;
27 | this.getData();
28 |
29 | setInterval(function() {
30 | self.getData()
31 | self.updateDom();
32 | }, this.config.updateInterval);
33 | },
34 |
35 | processData: function() {
36 | var self = this;
37 |
38 | if (this.loaded === false) { self.updateDom(self.config.animationSpeed) ; }
39 | this.loaded = true;
40 |
41 | },
42 |
43 | /*
44 | * getData
45 | * function returns data and shows it in the module wrapper
46 | * get Toothbrush Time
47 | *
48 | */
49 | getData: function() {
50 | var self = this;
51 | //this.loaded = false;
52 | this.sendSocketNotification("MMM-OralB-GET_DATA", this.config);
53 | this.loaded = true;
54 | },
55 |
56 | /* scheduleUpdate()
57 | * Schedule next update.
58 | *
59 | * argument delay number - Milliseconds before next update.
60 | * If empty, this.config.updateInterval is used.
61 | */
62 | scheduleUpdate: function(delay) {
63 | var nextLoad = this.config.updateInterval;
64 | if (typeof delay !== "undefined" && delay >= 0) {
65 | nextLoad = delay;
66 | }
67 | nextLoad = nextLoad ;
68 | var self = this;
69 | setTimeout(function() {
70 | self.getData();
71 |
72 | }, nextLoad);
73 | },
74 |
75 | getDom: function() {
76 | var self = this;
77 |
78 | // create element wrapper for show into the module
79 | var wrapper = document.createElement("div");
80 | wrapper.className = "small";
81 | if(!this.loaded) {
82 | wrapper.innerHTML = "Loading...";
83 | wrapper.classname = "small dimmed";
84 | return wrapper;
85 | }
86 |
87 | if (this.dataNotification) {
88 | if (this.debug) {
89 | console.log(this.dataNotification);
90 | }
91 |
92 | var wrapperDataNotification = document.createElement("div");
93 | var timelabel = document.createElement("label");
94 | timelabel.innerHTML = this.translate("Time") + this.dataNotification.brushingTime;
95 | wrapper.appendChild(timelabel);
96 |
97 | if (this.config.debug) {
98 | var d = new Date();
99 | var labelLastUpdate = document.createElement("label");
100 | labelLastUpdate.innerHTML = "
Updated: " + ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2)+ ":" + ("0" + d.getSeconds()).slice(-2) + "
Intervall: " + this.config.updateInterval/1000 + "s";
101 | wrapper.appendChild(labelLastUpdate);
102 | }
103 |
104 | return wrapper;
105 | }
106 | },
107 |
108 | getScripts: function() {
109 | return [];
110 | },
111 |
112 | getStyles: function () {
113 | return [
114 | "MMM-OralB.css", "font-awesome.css"
115 | ];
116 | },
117 |
118 | // Load translations files
119 | getTranslations: function() {
120 | return {
121 | en: "translations/en.json",
122 | es: "translations/es.json",
123 | de: "translations/de.json",
124 |
125 | };
126 | },
127 |
128 | // socketNotificationReceived from helper
129 | socketNotificationReceived: function (notification, payload) {
130 | if (this.debug) {
131 | console.log(notification, " by MMM-OralB.js received");
132 | }
133 |
134 | if(notification === "MMM-OralB-DISPLAY_DATA") {
135 | this.dataNotification = payload;
136 | this.updateDom();
137 | this.loaded = true;
138 | }
139 | },
140 |
141 | });
142 |
--------------------------------------------------------------------------------