Skip to content

Commit

Permalink
Added notification support via sendTo / blockly
Browse files Browse the repository at this point in the history
  • Loading branch information
klein0r committed May 24, 2023
1 parent f8286df commit 60f3f92
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 14 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ Buy here: [Aliexpress.com](https://haus-auto.com/p/ali/UlanziTC001) (Affiliate-L
Placeholder for the next version (at the beginning of the line):
### **WORK IN PROGRESS**
-->
### **WORK IN PROGRESS**

* (klein0r) Added notification support via sendTo / blockly

### 0.0.4 (2023-05-19)

* (klein0r) Added indicator support
Expand Down
204 changes: 204 additions & 0 deletions admin/blockly.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
'use strict';

if (typeof goog !== 'undefined') {
goog.provide('Blockly.JavaScript.Sendto');
goog.require('Blockly.JavaScript');
}

Blockly.Translate =
Blockly.Translate ||
function (word, lang) {
lang = lang || systemLang;
if (Blockly.Words && Blockly.Words[word]) {
return Blockly.Words[word][lang] || Blockly.Words[word].en;
} else {
return word;
}
};

/// --- SendTo Awtrix Light --------------------------------------------------
Blockly.Words['awtrix-light'] = {
en: 'Awtrix-light notification',
de: 'Awtrix-light Benachrichtigung',
ru: 'Awtrix-световое уведомление',
pt: 'Notificação de luz Awtrix',
nl: 'Vertaling:',
fr: 'Notification Awtrix-light',
it: 'Notifica di luce di Awtrix',
es: 'Alerta Awtrix-light',
pl: 'Awtrix-light notification',
uk: 'Awtrix-light повідомлення',
'zh-cn': '发出通知',
};
Blockly.Words['awtrix-light_message'] = {
en: 'Message',
de: 'Nachricht',
ru: 'Сообщение',
pt: 'Mensagem',
nl: 'Bericht',
fr: 'Message',
it: 'Messaggio',
es: 'Mensaje',
pl: 'Message',
uk: 'Новини',
'zh-cn': '导 言',
};
Blockly.Words['awtrix-light_sound'] = {
en: 'Sound',
de: 'Ton',
ru: 'Звук',
pt: 'Soa',
nl: 'Sound',
fr: 'Sound',
it: 'Suono',
es: 'Sonido',
pl: 'Sound',
uk: 'Звуковий',
'zh-cn': '保密',
};
Blockly.Words['awtrix-light_icon'] = {
en: 'Icon',
de: 'Icon',
ru: 'Икона',
pt: 'Ícone',
nl: 'Icon',
fr: 'Icon',
it: 'Icona',
es: 'Icon',
pl: 'Ikon',
uk: 'Ікона',
'zh-cn': '一. 导言',
};
Blockly.Words['awtrix-light_repeat'] = {
en: 'Repetitions',
de: 'Wiederholungen',
ru: 'Повторение',
pt: 'Repetições',
nl: 'Herhaling',
fr: 'Répétitions',
it: 'Ripetizioni',
es: 'Repeticiones',
pl: 'Repetycja',
uk: 'Рекорди',
'zh-cn': '重复',
};
Blockly.Words['awtrix-light_duration'] = {
en: 'Duration',
de: 'Dauer',
ru: 'Продолжительность',
pt: 'Duração',
nl: 'Vertaling:',
fr: 'Durée',
it: 'Durata',
es: 'Duración',
pl: 'Duracja',
uk: 'Тривалість',
'zh-cn': '期间',
};

Blockly.Words['awtrix-light_anyInstance'] = {
en: 'All instances',
de: 'Alle Instanzen',
ru: 'Все экземпляры',
pt: 'Todas as instâncias',
nl: 'Alle instanties',
fr: 'Toutes les instances',
it: 'Tutte le istanze',
es: 'Todas las instancias',
pl: 'Wszystkie instancje',
uk: 'Всі екземпляри',
'zh-cn': '所有案件',
};
Blockly.Words['awtrix-light_tooltip'] = {
en: 'Send notification to Awtrix',
de: 'Nachricht senden an Awtrix',
ru: 'Отправить уведомление в Awtrix',
pt: 'Enviar notificação para Awtrix',
nl: 'Stuur een bericht naar Awtrix',
fr: 'Envoyer la notification à Awtrix',
it: 'Invia notifica a Awtrix',
es: 'Enviar notificación a Awtrix',
pl: 'Powiadomienie Awtrix',
uk: 'Надіслати повідомлення на Awtrix',
'zh-cn': '向Awtrix发出通知',
};
Blockly.Words['awtrix-light_help'] = { en: 'http://github.com/klein0r/ioBroker.awtrix-light/blob/master/README.md', de: 'http://github.com/klein0r/ioBroker.awtrix-light/blob/master/README.md' };

Blockly.Sendto.blocks['awtrix-light'] =
'<block type="awtrix-light">' +
' <value name="INSTANCE">' +
' </value>' +
' <value name="MESSAGE">' +
' <shadow type="text">' +
' <field name="TEXT">haus-automatisierung.com</field>' +
' </shadow>' +
' </value>' +
' <value name="SOUND">' +
' </value>' +
' <value name="ICON">' +
' </value>' +
' <value name="REPEAT">' +
' <shadow type="math_number">' +
' <field name="NUM">1</field>' +
' </shadow>' +
' </value>' +
' <value name="DURATION">' +
' <shadow type="math_number">' +
' <field name="NUM">5</field>' +
' </shadow>' +
' </value>' +
'</block>';

Blockly.Blocks['awtrix-light'] = {
init: function () {
const options = [];
if (typeof main !== 'undefined' && main.instances) {
for (let i = 0; i < main.instances.length; i++) {
const m = main.instances[i].match(/^system.adapter.awtrix-light.(\d+)$/);
if (m) {
const n = parseInt(m[1], 10);
options.push(['awtrix-light.' + n, '.' + n]);
}
}
}

if (!options.length) {
for (let k = 0; k <= 4; k++) {
options.push(['awtrix-light.' + k, '.' + k]);
}
}
options.unshift([Blockly.Translate('awtrix-light_anyInstance'), '']);

this.appendDummyInput('INSTANCE').appendField(Blockly.Translate('awtrix-light')).appendField(new Blockly.FieldDropdown(options), 'INSTANCE');
this.appendValueInput('MESSAGE').appendField(Blockly.Translate('awtrix-light_message'));
this.appendValueInput('SOUND').appendField(Blockly.Translate('awtrix-light_sound'));
this.appendValueInput('ICON').appendField(Blockly.Translate('awtrix-light_icon'));
this.appendValueInput('REPEAT').appendField(Blockly.Translate('awtrix-light_repeat'));
this.appendValueInput('DURATION').appendField(Blockly.Translate('awtrix-light_duration'));

this.setInputsInline(false);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);

this.setColour(Blockly.Sendto.HUE);
this.setTooltip(Blockly.Translate('awtrix-light_tooltip'));
this.setHelpUrl(Blockly.Translate('awtrix-light_help'));
},
};

Blockly.JavaScript['awtrix-light'] = function (block) {
const message = Blockly.JavaScript.valueToCode(block, 'MESSAGE', Blockly.JavaScript.ORDER_ATOMIC);
const sound = Blockly.JavaScript.valueToCode(block, 'SOUND', Blockly.JavaScript.ORDER_ATOMIC);
const icon = Blockly.JavaScript.valueToCode(block, 'ICON', Blockly.JavaScript.ORDER_ATOMIC);
const repeat = parseInt(Blockly.JavaScript.valueToCode(block, 'REPEAT', Blockly.JavaScript.ORDER_ATOMIC));
const duration = parseInt(Blockly.JavaScript.valueToCode(block, 'DURATION', Blockly.JavaScript.ORDER_ATOMIC));

const objText = [];
message && objText.push('text: ' + message);
sound && objText.push('sound: ' + sound);
icon && objText.push('icon: ' + icon);
repeat && objText.push('repeat: ' + repeat);
duration && objText.push('duration: ' + duration);

return 'sendTo("awtrix-light' + block.getFieldValue('INSTANCE') + '", "notification", { ' + objText.join(', ') + ' }, (res) => { if (res && res.error) { console.error(res.error); } });';
};
3 changes: 2 additions & 1 deletion io-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
"compact": true,
"connectionType": "local",
"dataSource": "poll",
"blockly": true,
"messagebox": true,
"adminUI": {
"config": "json"
Expand Down Expand Up @@ -938,4 +939,4 @@
"native": {}
}
]
}
}
36 changes: 23 additions & 13 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class AwtrixLight extends utils.Adapter {
if (idNoNamespace === 'display.power') {
this.log.debug(`changing display power to ${state.val}`);

this.buildRequest('power', 'POST', { power: state.val }).then(async (response) => {
this.buildRequestAsync('power', 'POST', { power: state.val }).then(async (response) => {
if (response.status === 200 && response.data === 'OK') {
await this.setStateAsync(idNoNamespace, { val: state.val, ack: true });
}
Expand All @@ -75,7 +75,7 @@ class AwtrixLight extends utils.Adapter {
} else if (idNoNamespace === 'device.update') {
this.log.info('performing firmware update');

this.buildRequest('doupdate', 'POST')
this.buildRequestAsync('doupdate', 'POST')
.then(async (response) => {
if (response.status === 200 && response.data === 'OK') {
this.log.info('started firmware update');
Expand All @@ -85,7 +85,7 @@ class AwtrixLight extends utils.Adapter {
this.log.warn(`Unable to perform firmware update (maybe this is already the newest version): ${error}`);
});
} else if (idNoNamespace === 'device.reboot') {
this.buildRequest('reboot', 'POST').then(async (response) => {
this.buildRequestAsync('reboot', 'POST').then(async (response) => {
if (response.status === 200 && response.data === 'OK') {
this.log.info('rebooting device');
this.setApiConnected(false);
Expand All @@ -94,16 +94,16 @@ class AwtrixLight extends utils.Adapter {
} else if (idNoNamespace === 'apps.next') {
this.log.debug('switching to next app');

this.buildRequest('nextapp', 'POST');
this.buildRequestAsync('nextapp', 'POST');
} else if (idNoNamespace === 'apps.prev') {
this.log.debug('switching to previous app');

this.buildRequest('previousapp', 'POST');
this.buildRequestAsync('previousapp', 'POST');
} else if (idNoNamespace.startsWith('apps.')) {
if (idNoNamespace.endsWith('.visible')) {
const obj = await this.getObjectAsync(idNoNamespace);
if (obj && obj.native?.name) {
this.buildRequest('apps', 'POST', [{ name: obj.native.name, show: state.val }]).then(async (response) => {
this.buildRequestAsync('apps', 'POST', [{ name: obj.native.name, show: state.val }]).then(async (response) => {
if (response.status === 200 && response.data === 'OK') {
await this.setStateAsync(idNoNamespace, { val: state.val, ack: true });
}
Expand All @@ -113,7 +113,7 @@ class AwtrixLight extends utils.Adapter {
if (state.val) {
const obj = await this.getObjectAsync(idNoNamespace);
if (obj && obj.native?.name) {
this.buildRequest('switch', 'POST', { name: obj.native.name });
this.buildRequestAsync('switch', 'POST', { name: obj.native.name });
}
}
}
Expand Down Expand Up @@ -147,7 +147,17 @@ class AwtrixLight extends utils.Adapter {
if (obj && obj.message) {
// Notification
if (obj.command === 'notification' && typeof obj.message === 'object') {
// Todo
if (this.apiConnected) {
this.buildRequestAsync('notify', 'POST', obj.message)
.then((response) => {
this.sendTo(obj.from, obj.command, { error: null, data: response.data }, obj.callback);
})
.catch((error) => {
this.sendTo(obj.from, obj.command, { error }, obj.callback);
});
} else {
this.sendTo(obj.from, obj.command, { error: 'API is not connected (device offline ?)' }, obj.callback);
}
} else {
this.log.error(`[onMessage] Received incomplete message via "sendTo"`);

Expand Down Expand Up @@ -181,7 +191,7 @@ class AwtrixLight extends utils.Adapter {
this.refreshState();
}, 60000);

this.buildRequest('stats', 'GET')
this.buildRequestAsync('stats', 'GET')
.then(async (response) => {
if (response.status === 200) {
const content = response.data;
Expand Down Expand Up @@ -213,7 +223,7 @@ class AwtrixLight extends utils.Adapter {

refreshApps() {
if (this.apiConnected) {
this.buildRequest('apps', 'GET')
this.buildRequestAsync('apps', 'GET')
.then(async (response) => {
if (response.status === 200) {
const content = response.data;
Expand Down Expand Up @@ -352,7 +362,7 @@ class AwtrixLight extends utils.Adapter {
}
}

return this.buildRequest(`indicator${index}`, 'POST', indicatorValues[`indicator.${index}.active`] ? postObj : '');
return this.buildRequestAsync(`indicator${index}`, 'POST', indicatorValues[`indicator.${index}.active`] ? postObj : '');
}

async updateMoodlightByStates() {
Expand All @@ -372,10 +382,10 @@ class AwtrixLight extends utils.Adapter {
color: String(moodlightValues['display.moodlight.color']).toUpperCase(),
};

return this.buildRequest('moodlight', 'POST', moodlightValues['display.moodlight.active'] ? postObj : '');
return this.buildRequestAsync('moodlight', 'POST', moodlightValues['display.moodlight.active'] ? postObj : '');
}

buildRequest(service, method, data) {
buildRequestAsync(service, method, data) {
return new Promise((resolve, reject) => {
const url = `/api/${service}`;

Expand Down

0 comments on commit 60f3f92

Please sign in to comment.