NEWS
Alexa Shopping List mit Bring synchronisieren
-
Hallo zusammen,
da mich die Änderung seitens Amazon auch nervt habe ich auch mal auf die schnelle ein kleines TypeScript zusammengebastelt.
Es ist mit Sicherheit noch nicht perfekt, aber ein Anfang. Da ich es gerade erst fertig gestellt habe, hatte ich auch noch nicht die Möglichkeit und Zeit es ausgiebig zu testen.
Gerne stelle ich es aber hier allen Interessierten zur Verfügung.Zusätzliche Info:
Der Code-Dokumentationsblock am Anfang des Scripts gibt eine genauere Beschreibung des Scripts.
Nachdem Ihr den Inhalt der Textdatei in ein neues TypeScript kopiert habt, sollte es denke ich reichen die 5 Werte im Code-Block "SCRIPT SETUP" anzupassen.
JavaScript und TypeScript sind recht neu für mich und mit Sicherheit habe ich auch ungewollt das eine oder andere potentielle Problem ins Script eingebaut.
Ihr dürft mir natürlich gerne feedback geben.P.S. Ich habe gerade erst gesehen das @icastillo15 ebenfalls etwas gebastelt hat. Hätte ich mal erst hier gelesen, dann hätte ich mir meine Arbeit vielleicht sparen können.
:laughing: Ich werde sein Script auf jeden Fall in den nächsten Tagen ebenfalls mal testen.
Vielleicht kann ich ja was lernen.Grüße
Daniel
Script-File:
Shopping-List Sync.txt -
Moin. Weiß hier jemand, ob ein Adapter für Anylist oder Todoist in Arbeit ist?
Ich finde es zwar super, dass hier eine Lösung für den Sync zwischen Alexa und Bring erstellt wurde, aber leider gibt es für Bring kein Android-Widget, was für mich (bzw. meine Frau) ein großes Problem ist.
-
Moin. Weiß hier jemand, ob ein Adapter für Anylist oder Todoist in Arbeit ist?
Ich finde es zwar super, dass hier eine Lösung für den Sync zwischen Alexa und Bring erstellt wurde, aber leider gibt es für Bring kein Android-Widget, was für mich (bzw. meine Frau) ein großes Problem ist.
-
@dicken Danke, aber damit wird m.E. nicht die Todoist oder Anylist-Liste synchronisiert. Alle anderen Lösungen haben Nachteile, die wir möglichst vermeiden möchten. Das Widget der Alexa-Shoppinglist aktualisiert sich z.B. viel zu langsam und manchmal einige Stunden gar nicht. Die Bring-App hat kein Widget.
-
@dicken Danke, aber damit wird m.E. nicht die Todoist oder Anylist-Liste synchronisiert. Alle anderen Lösungen haben Nachteile, die wir möglichst vermeiden möchten. Das Widget der Alexa-Shoppinglist aktualisiert sich z.B. viel zu langsam und manchmal einige Stunden gar nicht. Die Bring-App hat kein Widget.
-
@dicken Danke, aber damit wird m.E. nicht die Todoist oder Anylist-Liste synchronisiert. Alle anderen Lösungen haben Nachteile, die wir möglichst vermeiden möchten. Das Widget der Alexa-Shoppinglist aktualisiert sich z.B. viel zu langsam und manchmal einige Stunden gar nicht. Die Bring-App hat kein Widget.
-
@mriceg sagte in Alexa Shopping List mit Bring synchronisieren:
Alexa-Shoppinglist aktualisiert sich z.B. viel zu langsam
welches meinst du?
Ro75.
-
@ro75 said in Alexa Shopping List mit Bring synchronisieren:
welches meinst du?
Das Widget von der Alexa-App
-
@mriceg mh, die Android - App reagiert bei mir sofort und auch im iobroker. Oder was meinst du?
Ro75.
-
@mriceg Die Eintragungen werden automatisch auf die Todoist App gesetzt. Aber wenn du sie dort als erledigt markierst, bleiben sie halt in der alexa einkaufsliste. Was mir aber relativ egal is, guck ich ja eh nicht drauf.
-
@dicken Ok. Das stimmt, in der Alexa-App ist es dann ja egal. Hauptsache, sie werden nicht immer wieder neu hinzugefügt. Ich werde das mal ausprobieren. Vielen Dank.
@Dicken Bei dem json muss vermutlich in Zeile 26 der API-Token von todoist hinterlegt werden, oder? Was muss sonst noch angepasst werden?
Kann man da nicht einbauen, dass der Eintrag auf der Alexa-Liste gelöscht wird, sobald er nach todoist übertragen wurde?
Edit:
OK, habe alles hinbekommen. Der API-Token muss in Zeile 27 hinter Bearer. In Zeile 20 muss noch die Projekt-ID eingetragen werden. -
Hallo zusammen,
ich habe mein Script nochmal aktualisiert. Es werden in Alexa nun automatisch alle Duplikate sofort wieder gelöscht. Außerdem wird nun erzwungen, dass Artikel mit einem Großbuchstaben beginnen.
Viel Spaß damit und gerne wieder testen :-)
Kleiner Nachtrag: wenn ich über Alexa Dinge hinzufüge und dann in Bring als erledigt markiere, dann werden diese bei mir in Alexa nicht mehr gelöscht. Das muss ich mir nochmal ansehen - könnte an den Zeitstempeln liegen.
Nachtrag 2: ging doch - mein Adapter war nur offline 😎
const bringBaseId = 'bring.0.0f0c420c-3298-4911-91f5-7ed0fbbfd36e'; const alexa2BaseId = 'alexa2.0.Lists.SHOPPING_LIST'; const bringListId = bringBaseId + '.content'; const bringListCompletedId = bringBaseId + '.recentContent'; const bringAddToList = bringBaseId + '.saveItem'; const bringCompleteItem = bringBaseId + '.moveToRecentContent'; const alexaAddToList = alexa2BaseId + '.#New'; const alexaListId = alexa2BaseId + '.json'; //switch off to silence: const printDebug = true; function debug(msg) { if (printDebug) { log(msg) } } const TodoItemStatus = { NeedsAction: 'needs_action', Completed: 'completed', }; /** * @typedef bringItem * @type {object} * @property {string} specification * @property {string} name * @property {string} status * @property {boolean} [found] - keep track if found or not. */ /** * @typedef alexaItem * @type {object} * @property {string} value * @property {string} id * @property {boolean} completed * @property {number} updatedDateTime * @property {boolean} [found] - keep track if found or not. */ /** * Compare alexaItem complete and bringItem status -> returns true if same status. * @param {Array<alexaItem>} alexaList * @param {Array<bringItem>} list * @returns {boolean} true if same status. */ function compareCompleted(alexaItem, bringItem) { if (alexaItem.completed && bringItem.status !== TodoItemStatus.Completed) { return false; } if (!alexaItem.completed && bringItem.status !== TodoItemStatus.NeedsAction) { return false; } return true; } function ListCleaner(Eintrag='') { const arr = Eintrag.split(' '); for (let i = 0; i < arr.length; i++) { arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].slice(1); } return arr.join(' '); } /** * sync lists * @param {Array<alexaItem>} alexaList * @param {Array<bringItem>} list * @param {number} timestampBring * @param {string} msource * @param {Array<bringItem>} recentList * @returns {Array<bringItem>} new bring List */ function syncLists(alexaList, list, timestampBring, msource, recentList) { const newBringList = []; var empty = true; for (const alexaItem of alexaList) { for (const bringItem of list) { empty = false; if (bringItem.name === alexaItem.value) { alexaItem.found = true; bringItem.found = true; //found item. Update completed state from 'newer' list: bringItem.status = TodoItemStatus.NeedsAction; if (alexaItem.updatedDateTime > timestampBring) { if (alexaItem.value !== bringItem.name || !compareCompleted(alexaItem, bringItem)) { if (msource === 'Alexa') { debug('Updating Bring item: ' + bringItem.name + ' from Alexa'); setState(bringCompleteItem, ListCleaner(bringItem.name)); } } } else { //keep bring: //update alexa: if (!compareCompleted(alexaItem, bringItem)) { if (msource === 'Bring') { bringItem.status = TodoItemStatus.Completed; debug('Update Alexa item: ' + alexaItem.value + ' to ' + (bringItem.status === TodoItemStatus.Completed ? 'done' : 'undone') + ' from Bring.'); setState(`${alexa2BaseId}.items.${alexaItem.id}.completed`, bringItem.status === TodoItemStatus.Completed); } } } } } for (const bringItemCompleted of recentList) { if (bringItemCompleted.name === alexaItem.value) { alexaItem.found = true; bringItemCompleted.found = true; //found item. Update completed state from 'newer' list: bringItemCompleted.status = TodoItemStatus.Completed; if (alexaItem.updatedDateTime > timestampBring) { if (alexaItem.value !== bringItemCompleted.name || !compareCompleted(alexaItem, bringItemCompleted)) { if (msource === 'Alexa') { debug('Adding Bring item: ' + bringItemCompleted.name + ' from Alexa'); setState(bringAddToList, ListCleaner(bringItemCompleted.name)); } } } else { //keep bring: //update alexa: if (!compareCompleted(alexaItem, bringItemCompleted)) { bringItemCompleted.status = TodoItemStatus.Completed; if (msource === 'Bring') { debug('Delete Alexa item: ' + alexaItem.value + ' from Bring.'); //setState(`${alexa2BaseId}.items.${alexaItem.id}.completed`, bringItemCompleted.status === TodoItemStatus.Completed); setState(`${alexa2BaseId}.items.${alexaItem.id}.#delete`, true); } } } } } if (!alexaItem.found) { //alexa item not found: if (alexaItem.completed) { debug('Delete ' + alexaItem.value + ' because done and not in Bring list.'); setState(`${alexa2BaseId}.items.${alexaItem.id}.#delete`, true); } else { if (msource === 'Alexa') { debug('Adding ' + alexaItem.value + ' to Bring list'); setState(bringAddToList, ListCleaner(alexaItem.value)); } } } if (empty === true) { if (alexaItem.updatedDateTime < timestampBring) { debug('Delete ' + alexaItem.value + ' from Alexa list because Bring list is all done.'); setState(`${alexa2BaseId}.items.${alexaItem.id}.#delete`, true); } } } for (const bringItem of list) { if (!bringItem.found) { if (bringItem.status === TodoItemStatus.Completed) { //debug('Remove from bring item: ' + bringItem.name + ' because done and not on alexa list'); //Not executed since I want to keep the recent items inside bring app } else { if (msource === 'Bring') { debug('Adding ' + bringItem.name + ' to Alexa list.'); setState(alexaAddToList, ListCleaner(bringItem.name)); } } } } return newBringList; } function doSync(source) { eliminateDuplicated(); const alexaList = JSON.parse(getState(alexaListId).val); const state = getState(bringListId); const bringList = JSON.parse(state.val); const state2 = getState(bringListCompletedId); const bringListCompleted = JSON.parse(state2.val); syncLists(alexaList, bringList, state.ts, source, bringListCompleted); } function eliminateDuplicated() { var myAlexaList = JSON.parse(getState(alexaListId).val); var arrayWithDuplicates = []; for(var alexaItem of myAlexaList) { var obj = {}; obj["value"] = ListCleaner(alexaItem.value); obj["id"] = alexaItem.id; arrayWithDuplicates.push(obj); } const lookup = arrayWithDuplicates.reduce((a, e) => { a[e.value] = ++a[e.value] || 0; return a; }, {}); const getKey = o => keys.map(k => o[k]).join('|'), keys = ['value'], myarray = arrayWithDuplicates.filter(e => lookup[e.value]), hash = Object.create(null), duplicates = myarray.filter(o => (k => (hash[k] = (hash[k] || 0) + 1) > 1) (getKey(o)) ); for(var item of duplicates) { debug('Delete Alexa item: ' + item.value + ' because duplicated.'); setState(`${alexa2BaseId}.items.${item.id}.#delete`, true); } } on({id: bringListId, change: 'any'}, e => { debug('Update triggered from Bring'); doSync('Bring'); }); on({id: alexaListId, change: 'any'}, e => { debug('Update triggered from Alexa'); doSync('Alexa'); }); doSync();@icastillo15 cooles Skript!
Das Skript synchronisiert bei mir einwandfrei zwischen Alexa und Bring. Aber immer nur eine zeitlang - danach schreiben weder Alexa2 noch Bring Instanz das Skript zu triggern.
Wenn ich die Instanzen oder den ioBroker neu starte, gehts wieder ne Weile, teilweise aber schon nach ner Stunde nicht mehr.
Im Log steht nichts, die Instanzen werden alle grün angezeigt, hat jemand eine Idee, wo ich nach der Ursache suchen muss? Hat sonst noch jemand ähnliche Probleme?
-
Ich habe immer wieder das Problem, dass die Eikaufsliste in dem Alexa2 Adapter nicht mehr vorhanden ist. dann laufen durch das script fehler auf.
z.B. jetzt aktuell, die Listen im Alexa2 sind alle weg. -
Bei mir sind seit kurzem auch alle Listen aus dem Alexa 2 Adapter weg...
Gibts noch jemanden bei dem dieser "Umweg" über das skript funktioniert oder ist das jetzt leider auch Geschichte...?
Schönen Gruß
Tom -
@Dicken Bei dem json muss vermutlich in Zeile 26 der API-Token von todoist hinterlegt werden, oder? Was muss sonst noch angepasst werden?
Kann man da nicht einbauen, dass der Eintrag auf der Alexa-Liste gelöscht wird, sobald er nach todoist übertragen wurde?
Edit:
OK, habe alles hinbekommen. Der API-Token muss in Zeile 27 hinter Bearer. In Zeile 20 muss noch die Projekt-ID eingetragen werden.Hallo @mriceg,
kannst du deine Anpassungen nochmal genauer beschreiben? Ich bekomme immer die Fehlermeldung "script.js.common.ToDoist.Einkaufsliste_via_Alexa: Error creating task:" und habe sicher einen Fehler bei der Eintragung der diversen Parameter für die Übertragung nach Todoist. Oder benötige ich noch einen Adapter?
Sorry für die vielen Fragen ;-)
Danke!Edit: Ich habe meinen Fehler gefunden - unsere Einkaufsliste ist eine geteilte Liste und ich habe nicht die project-id der Liste genommen, mit dessen Konto die erstellt wurde. Jetzt läuft das wunderbar.