Skip to content

Commit 38a7b15

Browse files
authored
Add files via upload
1 parent c9c602a commit 38a7b15

File tree

4 files changed

+390
-0
lines changed

4 files changed

+390
-0
lines changed

MMM-Navigate.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
body {
2+
background-color: black;
3+
}
4+
li {
5+
list-style-type: none;
6+
padding: 0;
7+
margin: 0;
8+
}
9+
li.selected {
10+
background: grey;
11+
}
12+
a:link {
13+
text-decoration: none;
14+
color: white;
15+
}
16+
a:visited {
17+
color: white;
18+
}
19+
a:hover {
20+
color: white
21+
}

MMM-Navigate.js

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
//MMM-Navigate.js:
2+
3+
Module.register("MMM-Navigate",{
4+
// Default module config.
5+
defaults: {
6+
Alias: [ 'Seite vorwärts','Seite zurück'],
7+
Action: [{type: "notification", title: 'Good morning!'},{type: "notification", title: 'Good morning!'}],
8+
GPIOPins: [26,20,19]//rotary cw, rotary ccw, rotary press (BCM Numbering)
9+
},
10+
11+
getStyles: function() {
12+
return [
13+
this.file('MMM-Navigate.css'), // css laden
14+
]
15+
},
16+
17+
sendAction: function(description) {
18+
this.show(0,{force: true});
19+
this.sendNotification(description.notification, description.payload);
20+
this.hide(10000);
21+
},
22+
23+
// Define start sequence.
24+
start: function() {
25+
Log.info("Starting module: " + this.name);
26+
this.sendConfig();//pass config to node_helper.js
27+
//Helper to test connection to node_helper.js
28+
//this.sendSocketNotification('START', {message: 'Starte Verbindung node_helper für ' + this.name});
29+
},
30+
31+
// Override dom generator.
32+
getDom: function() {
33+
//Div for loading
34+
if (this.loading) {
35+
var loading = document.createElement("div");
36+
loading.innerHTML = this.translate("LOADING");
37+
loading.className = "dimmed light small";
38+
wrapper.appendChild(loading);
39+
return wrapper
40+
}
41+
42+
var self = this;//makes variables usable in functions
43+
//Div after loading
44+
var parent = document.createElement("div");
45+
parent.className = "xsmall bright";
46+
parent.setAttribute('tabindex', 0);//set tabindex on div for focus purposes
47+
48+
//build navigation from array
49+
for (let index = 0; index < this.config.Action.length; index++) {
50+
var naviItem = document.createElement("li");
51+
var link = document.createElement('a');
52+
link.setAttribute('href', '');
53+
link.setAttribute('target', 'iframe_a');
54+
link.innerHTML = this.config.Alias[index];
55+
naviItem.setAttribute('id', index)
56+
if(index==0){//first li gets class="selected"
57+
naviItem.setAttribute('class', 'selected');
58+
}
59+
naviItem.append(link);
60+
parent.append(naviItem);
61+
}
62+
return parent
63+
},
64+
65+
sendConfig: function() {
66+
this.sendSocketNotification("BUTTON_CONFIG", {
67+
config: this.config
68+
});
69+
},
70+
71+
naviaction: function(payload){
72+
var self = this;
73+
var selectedid = '';
74+
var test = '';
75+
76+
if(payload.inputtype === 'CW'){
77+
self.show(0);
78+
selectedid = fselectedid();
79+
//console.log('FCW, selectedid: '+selectedid);
80+
81+
if(selectedid==''){//first li gets class="selected"
82+
document.getElementsByTagName('li')[0].setAttribute('class', 'selected');
83+
}else if(selectedid==self.config.Action.length-1){//last entry reached, set mark on first entry
84+
document.getElementsByTagName('li')[selectedid].setAttribute('class', '');
85+
document.getElementsByTagName('li')[0].setAttribute('class', 'selected');
86+
}else{//delete mark of selected id and mark next one
87+
document.getElementsByTagName('li')[selectedid].setAttribute('class', '');
88+
document.getElementsByTagName('li')[parseInt(selectedid)+1].setAttribute('class', 'selected');
89+
}
90+
}else if(payload.inputtype === 'CCW'){
91+
self.show(0);
92+
selectedid = fselectedid();
93+
94+
if(selectedid==''){
95+
document.getElementsByTagName('li')[self.config.Action.length-1].setAttribute('class', 'selected');
96+
}else if(selectedid==0){//first entry reached, set mark on last entry
97+
document.getElementsByTagName('li')[selectedid].setAttribute('class', '');
98+
document.getElementsByTagName('li')[self.config.Action.length-1].setAttribute('class', 'selected');
99+
}else{//delete mark of selected id and mark previous one
100+
document.getElementsByTagName('li')[selectedid].setAttribute('class', '');
101+
document.getElementsByTagName('li')[parseInt(selectedid)-1].setAttribute('class', 'selected');
102+
}
103+
}else if(payload.inputtype === 'pressed'){
104+
//console.log('Lockstring: ',this.lockStrings,' xxx ',this.hidden);
105+
self.show(0,{force: true});
106+
selectedid = fselectedid();
107+
//console.log('Alex, Payload: ', self.config.Action[selectedid].notification,' xxx ',self.config.Action[selectedid].payload);
108+
self.sendAction(self.config.Action[selectedid]);
109+
}
110+
111+
function fselectedid(){//get ID and return it
112+
for (let index = 0; index < self.config.Action.length; index++) {
113+
var test = document.getElementsByTagName('li')[index].getAttribute('class');
114+
115+
if(test=='selected'){
116+
var selectedid = document.getElementsByTagName('li')[index].getAttribute('id');
117+
}
118+
}
119+
return selectedid;
120+
}
121+
return parent
122+
},
123+
124+
// socketNotificationReceived from helper
125+
socketNotificationReceived: function (notification, payload) {
126+
if(notification === "{{MODULE_NAME}}-NOTIFICATION_TEST") {
127+
// set dataNotification
128+
this.dataNotification = payload;
129+
this.updateDom();
130+
}else if(notification === 'MSG'){
131+
//Log.info('MSG Testnofication von node_helper für MMM-Navigate erhalten, Payload: '+payload.message);
132+
}else if(notification === 'CW'){
133+
//console.log('Rotary Info CW erhalten');
134+
this.naviaction(payload);
135+
}else if(notification === 'CCW'){
136+
//console.log('Rotary Info CCW erhalten');
137+
this.naviaction(payload);
138+
}else if(notification === 'pressed'){
139+
//console.log('Rotary Info pressed erhalten');
140+
this.naviaction(payload);
141+
}
142+
},
143+
144+
});

node_helper.js

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
/* Magic Mirror
2+
* Node Helper: {MMM-Navigate}
3+
*
4+
* By {AxLED}
5+
* {MIT} Licensed.
6+
*/
7+
8+
//Debugging
9+
//tail -f ~/.pm2/logs/mm-out-0.log
10+
//tail -f ~/.pm2/logs/mm-error-0.log
11+
12+
const Gpio = require('onoff').Gpio
13+
const moment = require('moment');//needed for time
14+
var NodeHelper = require("node_helper");
15+
last_time = '';
16+
helfer = '';
17+
18+
module.exports = NodeHelper.create({
19+
// Subclass start method.
20+
start: function() {
21+
var self = this;
22+
//console.log("Starting node helper for: " + self.name);
23+
//this.intializeButtons();
24+
this.loaded = false;
25+
},
26+
27+
intializeButtons: function() {
28+
//Rotary Code...
29+
var self = this;
30+
31+
console.log('MMM-Navigate, listen on GPIO PINs (BCM): '+self.config.GPIOPins[0]+','+self.config.GPIOPins[1]+','+self.config.GPIOPins[2]);
32+
const A = new Gpio(self.config.GPIOPins[0], 'in', 'both',{debounceTimeout : 20 }) //BCM Pin 26
33+
const B = new Gpio(self.config.GPIOPins[1], 'in', 'both',{debounceTimeout : 20 }) //BCM Pin 20
34+
const C = new Gpio(self.config.GPIOPins[2], 'in', 'both',{debounceTimeout : 20 }) //BCM Pin 19*/
35+
36+
A.watch(function (err, value) {
37+
if (err) {
38+
throw err
39+
}
40+
//console.log('A triggered: ' + value)
41+
helfer = f2('A',value);
42+
})
43+
44+
B.watch(function (err, value) {
45+
if (err) {
46+
throw err
47+
}
48+
//console.log('B triggered: ' + value)
49+
helfer = f2('B',value);
50+
})
51+
52+
C.watch(function (err, value) {
53+
if (err) {
54+
throw err
55+
}
56+
//console.log('C triggered: ' + value)
57+
helfer = f2('C',value);
58+
})
59+
60+
//Variables
61+
seq_contacts = '';
62+
seq_value = '';
63+
action = '';
64+
65+
function f2(contact, value){
66+
seq_contacts = seq_contacts + contact;
67+
seq_value = seq_value + value;
68+
if(last_time==''){//set if not already set
69+
last_time = moment();
70+
}
71+
var b = moment();
72+
var vdiff = b.diff(last_time,'millisecond');
73+
74+
//for A & B ist timediff needed, for C not really
75+
if((seq_contacts.indexOf('A')!=-1 || seq_contacts.indexOf('B')!=-1) && (seq_contacts.indexOf('C')==-1)){
76+
if(vdiff>30){
77+
action = frichtung(seq_contacts+seq_value);
78+
//console.log('Zeitdifferenz:',b.diff(last_time,'millisecond'));
79+
//console.log('seq_contacts/value:', seq_contacts+seq_value);
80+
//console.log('action: ',action);
81+
sleep_ms(200);
82+
//reset variables
83+
last_time = '';
84+
seq_contacts = '';
85+
seq_value = '';
86+
}else if(vdiff>40){
87+
//console.log('Zeitdifferenz:',b.diff(last_time,'millisecond'));
88+
//console.log('seq_contacts/value:', seq_contacts+seq_value);
89+
//reset variables
90+
last_time = '';
91+
seq_contacts = '';
92+
seq_value = '';
93+
}
94+
95+
}else if(seq_contacts.indexOf('C')!=-1){//only react on C0 which is C-Button Press (not C-Button UP)
96+
97+
//console.log('C');
98+
action = frichtung('C0');
99+
//console.log('Zeitdifferenz:',b.diff(last_time,'millisecond'));
100+
//console.log('seq_contacts/value:', seq_contacts+seq_value);
101+
//console.log('action: ',action);
102+
sleep_ms(250);
103+
//reset variables
104+
last_time = '';
105+
seq_contacts = '';
106+
seq_value = '';
107+
}
108+
109+
if(action=='CW'){
110+
self.sendSocketNotification('CW',{inputtype: 'CW'});
111+
action = '';
112+
return;
113+
}else if(action=='CCW'){
114+
self.sendSocketNotification('CCW',{inputtype: 'CCW'});
115+
action = '';
116+
return;
117+
}else if(action=='pressed'){
118+
self.sendSocketNotification('pressed',{inputtype: 'pressed'});
119+
action = '';
120+
return;
121+
}
122+
action = '';
123+
return;
124+
}
125+
126+
// Milliseconds
127+
function sleep_ms(millisecs) {
128+
var initiation = new Date().getTime();
129+
while ((new Date().getTime() - initiation) < millisecs);
130+
}
131+
132+
function frichtung(seq){
133+
switch(seq){
134+
//CW
135+
case 'A0':
136+
case 'AA00':
137+
case 'AA10':
138+
case 'AB00':
139+
case 'AB01':
140+
case 'AB11':
141+
case 'ABA010':
142+
case 'ABA000':
143+
case 'ABABAB110011':
144+
case 'BA01':
145+
case 'BA10':
146+
case 'BAABA10001':
147+
case 'BAA010':
148+
case 'BAB011':
149+
case 'BABA1001':
150+
case 'BABAB00011':
151+
case 'BABAB10011':
152+
case 'BABAB10010':
153+
case 'BABA0001':
154+
case 'AABAB10011':
155+
case 'ABA001':
156+
case 'BAABA00001':
157+
case 'BAABB10001':
158+
seq = 'CW';
159+
return seq;
160+
break;
161+
//CCW
162+
case 'AB01':
163+
case 'AB10':
164+
case 'ABA000':
165+
case 'ABA011':
166+
case 'ABB001':
167+
case 'ABAA1000':
168+
case 'ABABA10000':
169+
case 'ABABB10001':
170+
case 'B0':
171+
case 'BA00':
172+
case 'BA11':
173+
case 'BB01':
174+
case 'BB10':
175+
case 'BAA000':
176+
case 'BAB001':
177+
case 'BABABB000001':
178+
case 'BABABA010001':
179+
case 'BBAB1001':
180+
case 'BBABA10001':
181+
case 'BBABA10000':
182+
case 'BBABB10001':
183+
case 'ABABA10011':
184+
case 'ABAB1001':
185+
seq = 'CCW';
186+
return seq;
187+
break;
188+
//Rotary pressed
189+
case 'C0':
190+
case 'CC00':
191+
case 'CC01':
192+
case 'CC10':
193+
case 'CCCC1010':
194+
seq = 'pressed';
195+
return seq;
196+
break;
197+
}
198+
}
199+
},
200+
201+
202+
// Override socketNotificationReceived method.
203+
socketNotificationReceived: function(notification, payload) {
204+
if (notification === 'START') {
205+
console.log("Working notification system. Notification:", notification, "payload: ", payload);
206+
// Send notification
207+
this.sendSocketNotification('MSG', {message: 'test'});
208+
}else if (notification === 'BUTTON_CONFIG') {
209+
this.config = payload.config;
210+
this.intializeButtons();
211+
};
212+
},
213+
214+
});

package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "MagicMirror-Module-Navigate",
3+
"version": "1.0.0",
4+
"description": "A module to connect a rotary encoder for MM Navigation",
5+
"main": "MMM-Navigate.js",
6+
"author": "AxLED",
7+
"license": "MIT",
8+
"dependencies": {
9+
"onoff": "latest"
10+
}
11+
}

0 commit comments

Comments
 (0)