mrbungle64 / ioBroker.ecovacs-deebot

Control your Ecovacs Deebot and yeedi vacuum cleaner with ioBroker
MIT License
65 stars 11 forks source link

Deebot Ozmo 950 #7

Closed gigasi closed 4 years ago

gigasi commented 4 years ago

Hallo, wird es irgendwann auch mal ein Support für Deebot Ozmo 950 geben?

mrbungle64 commented 4 years ago

@mrbungle64 kannst du dir das mit dem failure Code 1 nochmal ansehen (s.a. oben)? Das kommt auch seit dem refactoring (statt des 500 timeouts, der requests geht gar nicht erst raus) [EcovacsMQTT] call failed with {"ret":"fail","errno":1,"error":"no td in request"} [EcovacsMQTT] failure code: 1 [EcovacsMQTT] error send_command: failure code: 1

@boriswerner Es sollte nun wieder der bekannte Fehler kommen... Hast Du eine Idee warum der Server nicht antwortet und der Timeout kommt?

boriswerner commented 4 years ago

Es sollte nun wieder der bekannte Fehler kommen...

Der ist nun wieder da, ja.

Hast Du eine Idee warum der Server nicht antwortet und der Timeout kommt?

Leider nein. Bisher hab ich mich nur mit der Nachrichtenauswertung beschäftigt um mich einzuarbeiten, nicht mit dem Senden von Befehlen (ich weiß, der wichtigere Teil ;-)

boriswerner commented 4 years ago

Ich habe noch einen Fehler bzgl. des json-bodys behoben (siehe Pull Request). Außerdem habe ich mir den Aufruf einmal näher angesehen und auch mal testweise einen Aufruf über Powershell gemacht (die Session habe ich über das js aufgebaut und dann den Request kopiert und nochmal über Powershell rausgeschickt). Leider mit dem gleichen Timeout:

Invoke-WebRequest  https://portal-eu.ecouser.net/api/iot/devmanager.do?mid=yna5xi"&"did=e0bc19bb-8cb1-43e3-8503-e9f810e35d36"&"td=q"&"u=eaetn1jec3c37fcc"&"cv=1.67.3"&"t=a"&"av=1.3.1 `
-Method 'POST' `
-Headers @{'Content-Length'='390';'User-Agent'='Dalvik/2.1.0 (Linux; U; Android 5.1.1; A5010 Build/LMY48Z)'} `
-ContentType "application/json; charset=utf-8" `
-Body '{"auth":{"realm":"ecouser.net","resource":"59a4711e","token":"adOIEHFe5psyZBbUWzQcD5M1p4VnNKYT","userid":"eaetn1jec3c37fcc","with":"users"},"cmdName":"GetWaterPermeability","payload":{"header":{"pri":"2","ts":1581584005235,"tmz":480,"ver":"0.0.22"},"body":{"data":{"id":"36862970"}}},"payloadType":"j","td":"q","toId":"e0bc19bb-8cb1-43e3-8503-e9f810e35d36","toRes":"BTKk","toType":"yna5xi"}'

ergibt dann

StatusCode        : 200
StatusDescription : OK
Content           : {"ret":"fail","errno":500,"debug":"wait for response timed out"}
RawContent        : HTTP/1.1 200 OK
                    Connection: keep-alive
                    Content-Length: 64
                    Content-Type: application/json; charset=utf-8
                    Date: Thu, 13 Feb 2020 09:06:13 GMT
                    ETag: W/"40-ueTfLP0S94dV4Tk1owTh/w"
                    Server: nginx/1.15...
Forms             : {}
Headers           : {[Connection, keep-alive], [Content-Length, 64], [Content-Type, application/json; charset=utf-8],
                    [Date, Thu, 13 Feb 2020 09:06:13 GMT]...}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 64

Ich habe auch versucht die python-Applikation (https://github.com/And3rsL/Deebotozmo) zum laufen zu bekommen, die ja funktionieren soll, aber da scheitere ich leider daran, dass mir nach der Installation fehlende Module angemeckert werden, wenn ich sie nachinstallieren will, sagt pip aber, dass sie bereits da sind... Wäre interessant zu sehen, was das im logging für Aufrufe ausspuckt und ob doch irgendwas anders ist.

Du übergibst im Body standardmäßig noch eine request-id, die konnte ich im Python Code nicht entdecken. Kommt das von einem anderen Deebot als dem 950?

mrbungle64 commented 4 years ago

Ich habe noch einen Fehler bzgl. des json-bodys behoben (siehe Pull Request).

Pull request ist gemerged :+1:

... Du übergibst im Body standardmäßig noch eine request-id, die konnte ich im Python Code nicht entdecken. Kommt das von einem anderen Deebot als dem 950?

Ja richtig, das ist für "meinen" Deebot Ozmo 930 notwendig. Du kannst es ja mal testen ob es beim Ozmo 950 ohne diese ID (besser) funktioniert.

boriswerner commented 4 years ago

Durchbruch :-) Ich hab das mit der Python-App einmal durchgespielt und die "cmdName" Ausprägungen müssen kleingeschrieben werden. Nun spielt der kleine zumindest den "Ich bin hier" Sound ab. Z.B. "cmdName": "playSound", statt "cmdName": "PlaySound", Allerdings bekomme ich nun noch einen anderen Fehler, der mir das log zumüllt, ich forsche weiter:

@#[line:0,col:undefined]
[xmldom error]  element parse error: TypeError: source.indexOf is not a function

Beim handling der response funktioniert die JsonValidierung nicht (eigenes logging hinzugefügt):

[EcovacsMQTT] _handle_command_response() action: PlaySound { name: 'playSound', args: [Object] }
[EcovacsMQTT] _handle_command_response() command: playSound
[EcovacsMQTT] _handle_command_response() message: {"ret":"ok","resp":{"header":{"pri":1,"tzm":480,"ts":"1581595472502","ver":"0.0.1","fwVer":"1.7.6","hwVer":"0.1.1"},"body":{"code":0,"msg":"ok"}},"id":"Mck3"}
[EcovacsMQTT] _handle_command_response() resp(0): playSound null
[tools] isValidJsonString() str: { header: [Object], body: [Object] }
[tools] isValidJsonString() false
[VacBot] deviceClass: yna5xi
[VacBot] Ozmo 950 detected
[tools] isValidJsonString() str: { header: [Object], body: [Object] }
[tools] isValidJsonString() false
[EcovacsMQTT] _command_to_dict_api() isValidJsonString: false
[VacBot] deviceClass: yna5xi
[VacBot] Ozmo 950 detected
[EcovacsMQTT] _command_to_dict_api() isOzmo950: true
[EcovacsMQTT] error send_command: SyntaxError: Unexpected token o in JSON at position 1

Bei einigen kommt auch nach der Kleinschreibung noch ein Timeout. Das muss man wohl im einzelnen prüfen. Folgende kommen schonmal zurück:

[EcovacsMQTT] _handle_command_response() action: GetChargeState { name: 'getChargeState', args: [Object] }
[EcovacsMQTT] _handle_command_response() command: getChargeState
[EcovacsMQTT] _handle_command_response() message: {"ret":"ok","resp":{"header":{"pri":1,"tzm":480,"ts":"1581595663888","ver":"0.0.1","fwVer":"1.7.6","hwVer":"0.1.1"},"body":{"code":0,"msg":"ok","data":{"isCharging":0,"mode":"slot"}}},"id":"j8rB"}
[EcovacsMQTT] _handle_command_response() resp(0): getChargeState null
[tools] isValidJsonString() str: { header: [Object], body: [Object] }
[tools] isValidJsonString() false
[VacBot] deviceClass: yna5xi
[VacBot] Ozmo 950 detected
[tools] isValidJsonString() str: { header: [Object], body: [Object] }
[tools] isValidJsonString() false
[EcovacsMQTT] _command_to_dict_api() isValidJsonString: false
[VacBot] deviceClass: yna5xi
[VacBot] Ozmo 950 detected
[EcovacsMQTT] _command_to_dict_api() isOzmo950: true
[EcovacsMQTT] error send_command: SyntaxError: Unexpected token o in JSON at position 1
[EcovacsMQTT] (request statusCode: 200
[EcovacsMQTT] (request statusMessage: OK
[EcovacsMQTT] (request url:
[EcovacsMQTT] (request urlPathArgs: undefined
[EcovacsMQTT] (request headers: {
  server: 'nginx/1.15.8',
  date: 'Thu, 13 Feb 2020 12:07:45 GMT',
  'content-type': 'application/json; charset=utf-8',
  'content-length': '184',
  connection: 'close',
  'x-powered-by': 'Express',
  etag: 'W/"b8-k2hMmFc7svH7qfqoXJ79fQ"'
}
[EcovacsMQTT] _handle_command_response() action: GetLifeSpan { name: 'getLifeSpan', args: [Object] }
[EcovacsMQTT] _handle_command_response() command: getLifeSpan
[EcovacsMQTT] _handle_command_response() message: {"ret":"ok","resp":{"header":{"pri":1,"tzm":480,"ts":"1581595663893","ver":"0.0.1","fwVer":"1.7.6","hwVer":"0.1.1"},"body":{"code":10000,"msg":"data content has nothing"}},"id":"zxbd"}
[EcovacsMQTT] _handle_command_response() resp(0): getLifeSpan null
[tools] isValidJsonString() str: { header: [Object], body: [Object] }
[tools] isValidJsonString() false
[VacBot] deviceClass: yna5xi
[VacBot] Ozmo 950 detected
[tools] isValidJsonString() str: { header: [Object], body: [Object] }
[tools] isValidJsonString() false
[EcovacsMQTT] _command_to_dict_api() isValidJsonString: false
[VacBot] deviceClass: yna5xi
[VacBot] Ozmo 950 detected
[EcovacsMQTT] _command_to_dict_api() isOzmo950: true
[EcovacsMQTT] error send_command: SyntaxError: Unexpected token o in JSON at position 1
[EcovacsMQTT] (request statusCode: 200
[EcovacsMQTT] (request statusMessage: OK
[EcovacsMQTT] (request url:
[EcovacsMQTT] (request urlPathArgs: undefined
[EcovacsMQTT] (request headers: {
  server: 'nginx/1.15.8',
  date: 'Thu, 13 Feb 2020 12:07:45 GMT',
  'content-type': 'application/json; charset=utf-8',
  'content-length': '184',
  connection: 'close',
  'x-powered-by': 'Express',
  etag: 'W/"b8-Af+GVf9KAq4qO0TLWoLq0g"'
}
[EcovacsMQTT] _handle_command_response() action: GetLifeSpan { name: 'getLifeSpan', args: [Object] }
[EcovacsMQTT] _handle_command_response() command: getLifeSpan
[EcovacsMQTT] _handle_command_response() message: {"ret":"ok","resp":{"header":{"pri":1,"tzm":480,"ts":"1581595663899","ver":"0.0.1","fwVer":"1.7.6","hwVer":"0.1.1"},"body":{"code":10000,"msg":"data content has nothing"}},"id":"FU1T"}
[EcovacsMQTT] _handle_command_response() resp(0): getLifeSpan null
[tools] isValidJsonString() str: { header: [Object], body: [Object] }
[tools] isValidJsonString() false
[VacBot] deviceClass: yna5xi
[VacBot] Ozmo 950 detected
[tools] isValidJsonString() str: { header: [Object], body: [Object] }
[tools] isValidJsonString() false
[EcovacsMQTT] _command_to_dict_api() isValidJsonString: false
[VacBot] deviceClass: yna5xi
[VacBot] Ozmo 950 detected
[EcovacsMQTT] _command_to_dict_api() isOzmo950: true
[EcovacsMQTT] error send_command: SyntaxError: Unexpected token o in JSON at position 1
[EcovacsMQTT] (request statusCode: 200
[EcovacsMQTT] (request statusMessage: OK
[EcovacsMQTT] (request url:
[EcovacsMQTT] (request urlPathArgs: undefined
[EcovacsMQTT] (request headers: {
  server: 'nginx/1.15.8',
  date: 'Thu, 13 Feb 2020 12:07:45 GMT',
  'content-type': 'application/json; charset=utf-8',
  'content-length': '184',
  connection: 'close',
  'x-powered-by': 'Express',
  etag: 'W/"b8-a8HSHHntX5R8EmwuZsN+fw"'
}
[EcovacsMQTT] _handle_command_response() action: GetLifeSpan { name: 'getLifeSpan', args: [Object] }
[EcovacsMQTT] _handle_command_response() command: getLifeSpan
[EcovacsMQTT] _handle_command_response() message: {"ret":"ok","resp":{"header":{"pri":1,"tzm":480,"ts":"1581595663906","ver":"0.0.1","fwVer":"1.7.6","hwVer":"0.1.1"},"body":{"code":10000,"msg":"data content has nothing"}},"id":"R1xD"}
[EcovacsMQTT] _handle_command_response() resp(0): getLifeSpan null
[tools] isValidJsonString() str: { header: [Object], body: [Object] }
[tools] isValidJsonString() false
[VacBot] deviceClass: yna5xi
[VacBot] Ozmo 950 detected
[tools] isValidJsonString() str: { header: [Object], body: [Object] }
[tools] isValidJsonString() false
[EcovacsMQTT] _command_to_dict_api() isValidJsonString: false
[VacBot] deviceClass: yna5xi
[VacBot] Ozmo 950 detected
[EcovacsMQTT] _command_to_dict_api() isOzmo950: true
[EcovacsMQTT] error send_command: SyntaxError: Unexpected token o in JSON at position 1

Den Arbeitsstand kann man in meinem Fork (Commit siehe https://github.com/boriswerner/ecovacs-deebot.js/commit/f6ab790d68fa040c39524c200b12d9e7a6b1382e) sehen. Durch die Kleinschreibung der commands ist das aber wahrscheinlich inkompatibel mit dem 930, richtig?

mrbungle64 commented 4 years ago

Durchbruch :-)

Das freut mich zu hören! :+1:

... Den Arbeitsstand kann man in meinem Fork (Commit siehe boriswerner/ecovacs-deebot.js@f6ab790) sehen. Durch die Kleinschreibung der commands ist das aber wahrscheinlich inkompatibel mit dem 930, richtig?

Ja genau, und wahrscheinlich auch zu allen (oder zumindest sämtlichen) anderen Modellen. Meine beiden Geräte (und auch andere) erwarten wohl 'PascalCase' - der Ozmo 950 dann wohl 'camelCase'. Da müsste man sich wohl noch was überlegen, wie man das (ohne zu viel Aufwand) Modell-anhängig gestalten könnte...

boriswerner commented 4 years ago

Du kannst es ja mal testen ob es beim Ozmo 950 ohne diese ID (besser) funktioniert.

Mit ist auf jeden Fall kein Problem.

Ja genau, und wahrscheinlich auch zu allen (oder zumindest sämtlichen) anderen Modellen. Meine beiden Geräte (und auch andere) erwarten wohl 'PascalCase' - der Ozmo 950 dann wohl 'camelCase'. Da müsste man sich wohl noch was überlegen, wie man das (ohne zu viel Aufwand) Modell-anhängig gestalten könnte..

Mit dem PowerShell Skript kann man sehr gut testen, ich werde dann bei Gelegenheit mal alle bekannten Befehle testen. Bestenfalls baut man sich dann ein dictionary auf, dass einem für jeden Befehl dann bei Übergabe des jeweiligen Modells den entsprechenden Befehl mitgibt. Mit welcher Struktur das in JavaScript am besten geht ist wohl noch herauszufinden ;-) Außer es ist wirklich immer der gleiche Befehl nur in camelCase, das wäre natürlich einfach. Scheint es aber auf den ersten Blick nicht zu sein.

Und dann ist da noch das Problem zu lösen, warum er die result message nicht als valides JSON parsen kann...

boriswerner commented 4 years ago

Okay, es scheint in einigen Fällen mit camelCase zu gehen, andere Befehle sind aber wohl komplett anders. Hier meine Findings:

GetWaterPermeability gibt es wohl nicht (ist auch in der Python Library nicht implementiert) GetCleanState muss wohl der Befehl getCleanInfo sein GetBatteryInfo muss wohl der Befehl getBattery sein GetCleanSpeed muss wohl der Befehl getSpeed sein

Und dann noch ein Fehler: bei GetLifeSpan wird derzeit kein body mitgegeben, es kommt type = undefined. Muss nur das jeweilige Wort in [] enthalten, die Komponenten heißen auch anders (brush, sideBrush und heap):

"body": {
    "data": [
        "brush"
     ]
}
mrbungle64 commented 4 years ago

Okay, es scheint in einigen Fällen mit camelCase zu gehen, andere Befehle sind aber wohl komplett anders. Hier meine Findings:

GetWaterPermeability gibt es wohl nicht (ist auch in der Python Library nicht implementiert)

Damit kann man beim Ozmo 930 die Wasserzufuhrstärke abfragen. Für den Ozmo 950 ist das dann wohl anders benannt ...

GetCleanState muss wohl der Befehl getCleanInfo sein GetBatteryInfo muss wohl der Befehl getBattery sein GetCleanSpeed muss wohl der Befehl getSpeed sein

ok, habe das nun auch in dem Python Modul gefunden ... Da das ein bisschen anders strukturiert ist, waren mir die Unterschiede nicht aufgefallen.

... die Komponenten heißen auch anders (brush, sideBrush und heap):

Das hatte ich auch schon begonnen für den Ozmo 950 zu implementieren - aber offensichtlich hat es dann noch nicht richtig gegriffen:

ecovacsConstants:

exports.COMPONENT_TO_OZMO950 = {
    'main_brush': 'brush',
    'side_brush': 'sideBrush',
    'filter': 'heap'
};

index.js

if (this.isOzmo950()) {
    component = constants.COMPONENT_TO_OZMO950[component];
}
mrbungle64 commented 4 years ago

Ja genau, und wahrscheinlich auch zu allen (oder zumindest sämtlichen) anderen Modellen. Meine beiden Geräte (und auch andere) erwarten wohl 'PascalCase' - der Ozmo 950 dann wohl 'camelCase'. Da müsste man sich wohl noch was überlegen, wie man das (ohne zu viel Aufwand) Modell-anhängig gestalten könnte..

Mit dem PowerShell Skript kann man sehr gut testen, ich werde dann bei Gelegenheit mal alle bekannten Befehle testen. Bestenfalls baut man sich dann ein dictionary auf, dass einem für jeden Befehl dann bei Übergabe des jeweiligen Modells den entsprechenden Befehl mitgibt. Mit welcher Struktur das in JavaScript am besten geht ist wohl noch herauszufinden ;-) ...

Man könnte für den Anfang - bis wir sämtliche Modell-Varianten zum Laufen bekommen haben - die deviceClass mit übergeben und das dann in der vacBotCommand und den davon abgeleiteten Klassen behandeln.

this.send_command(new vacBotCommand.PlaySound(this.deviceClass));

Was hältst Du davon?

Ist nicht schön, aber früher oder später sollte das Ganze eh mal einem kompletten Refactoring unterzogen werden ...

boriswerner commented 4 years ago

... die Komponenten heißen auch anders (brush, sideBrush und heap):

Das hatte ich auch schon begonnen für den Ozmo 950 zu implementieren - aber offensichtlich hat es dann noch nicht richtig gegriffen:

Das könnte sogar greifen, es fehlt ja der body, daher hab ich es noch nicht bis ins letzte geprüft. Letztlich wird das switch-case mit den ganzen Ozmo950 Fallunterscheidungen, die man dann machen muss auch nicht übersichtlicher... Vielleicht sollte das besser in die vacBotCommand.js und dann definiert man die Kommandos einmal abstrakt und dann macht man dort das Mapping, Es wird ja an vielen Stellen hin- und herübersetzt (tools.js, index.js, vacBotCommand.js, ...)

Update: Da warst du schneller... 🥇 Finde ich gut

mrbungle64 commented 4 years ago

... die Komponenten heißen auch anders (brush, sideBrush und heap):

Das hatte ich auch schon begonnen für den Ozmo 950 zu implementieren - aber offensichtlich hat es dann noch nicht richtig gegriffen:

Das könnte sogar greifen, es fehlt ja der body, daher hab ich es noch nicht bis ins letzte geprüft. Letztlich wird das switch-case mit den ganzen Ozmo950 Fallunterscheidungen, die man dann machen muss auch nicht übersichtlicher... Vielleicht sollte das besser in die vacBotCommand.js und dann definiert man die Kommandos einmal abstrakt und dann macht man dort das Mapping, Es wird ja an vielen Stellen hin- und herübersetzt (tools.js, index.js, vacBotCommand.js, ...)

Update: Da warst du schneller... Finde ich gut

Gut :+1:

Kommst Du gerade dazu oder soll ich das nacher mal angehen? Hätte später am Abend 1-2 Stunden dafür.

boriswerner commented 4 years ago

Kommst Du gerade dazu oder soll ich das nacher mal angehen? Hätte später am Abend 1-2 Stunden dafür.

Heute komme ich leider zu nichts mehr. Morgen kann ich aber wieder was tun. Ich kann mich dann aber auch gut mit dem response-Problem beschäftigen ;-) Schau einfach wie weit du kommst, dann guck ich wo ich morgen weitermachen kann. 👍

Gerade noch zufällig bei bumper gefunden: https://github.com/bmartin5692/bumper/issues/71 Da sind einige interessante Logs vom 950 wo man sich sicherlich das ein oder andere Kommando abschauen kann :-)

mrbungle64 commented 4 years ago

Kommst Du gerade dazu oder soll ich das nacher mal angehen? Hätte später am Abend 1-2 Stunden dafür.

Heute komme ich leider zu nichts mehr. Morgen kann ich aber wieder was tun. Ich kann mich dann aber auch gut mit dem response-Problem beschäftigen ;-) Schau einfach wie weit du kommst, dann guck ich wo ich morgen weitermachen kann.

@boriswerner Ich habe noch eine andere Idee wie man die Kommandos für den Ozmo 950 mappen kann:

ecovacsMQTT.js

    send_command(action, recipient) {
        if (this.bot.isOzmo950()) {
            if (constants.COMMAND_TO_OZMO950[action.name]) {
                action.name = constants.COMMAND_TO_OZMO950[action.name];
            }
        }
        let c = this._wrap_command(action, recipient);
        ...
    }

ecovacsConstants.js

exports.COMMAND_TO_OZMO950 = {
    'Clean': 'clean',
    'Charge': 'charge',
    'SetTime': 'setTime',
    'PlaySound': 'playSound',
    'GetLifeSpan': 'getLifeSpan',
    'GetBatteryInfo': 'getBattery',
    'GetCleanState': 'getCleanInfo',
    'GetCleanSpeed': 'getCleanSpeed',
    'GetChargeState': 'getChargeState',
    'GetWaterBoxInfo': 'getWaterInfo',
    'GetWaterPermeability': 'getWaterInfo',
    'SetWaterPermeability': 'setWaterPermeability'
};

Gerade noch zufällig bei bumper gefunden: bmartin5692/bumper#71 Da sind einige interessante Logs vom 950 wo man sich sicherlich das ein oder andere Kommando abschauen kann :-)

Das ist natürlich extrem hilfreich :+1: Hab die ersten Fundstellen oben schon dazu gepackt

boriswerner commented 4 years ago

@mrbungle64 das funktioniert für die "get" sendCommands auf jeden Fall schon gut. clean funktioniert so noch nicht, siehe unten.

Ich vermute aber, dass wir nicht wirklich drumherumkommen den 950 nochmal deutlicher zu trennen. Bei getLifeSpan ist schon das erste größere Problem, da hier auch das Format des bodys anders ist und nicht nur die Bezeichnung. Der 950 erwartet "body": {"data": ["brush"]} statt "body":{"data":{"type":"brush"}} Die Antwort ist sonst "body":{"code":10000,"msg":"data content has nothing"}

Das clean Kommando gibt auch nur folgenden Fehler zurück: "body":{"code":20011,"msg":"get act error"} Der Aufruf beinhaltet derzeit: data":{"clean":{"type":"auto","speed":"standard","act":"s"} Erwartet wird hier für den 950 aber: "data": {"act": "start","type": "auto"} Also auch hier wieder ein Strukturunterschied zusätzlich zum unterschiedlichen Begriff im act.

Ich mache jetzt erstmal ein wenig Theorie-Arbeit und eine Liste für den 950 mit cmdName und zugehörigem body für das senden eines Kommandos responses und dazugehörigem body für das Verarbeiten einer eingehenden Nachricht Dann versuche ich mal das irgendwie übersichtlich auszulagern.

Ein positives Ergebnis habe ich für heute dann aber doch geschaffen: Ich hab aber einen Pull Request gestellt mit der Korrektur der JSON response-Erkennung. Die funktioniert nun :-) Da sind auch noch ein paar andere Änderungen dabei (water level und batterystatus), die du bitte einmal prüfen müsstest (siehe Beschreibung im Pull Request)..

boriswerner commented 4 years ago

Das response-handling funktioniert so auch nicht gut für den 950. Bisher wird auf topic.name geprüft. Das ist aber für den 950 undefined. Daher greift im Moment nur die _body_data_to_command, die auf Basis des body-Inhalts auf die Nachricht schließt. Das ist nicht so fein. Als topic kommt z.B. sowas zurück: iot/atr/onCleanInfo/[...] Damit lassen sich die Nachrichten gut unterscheiden.

Ich habe mal eine Übersicht angefangen, als Excel im Anhang 950_API.xlsx

mrbungle64 commented 4 years ago

@boriswerner

@mrbungle64 das funktioniert für die "get" sendCommands auf jeden Fall schon gut.

Das ist ja schon mal erfreulich :+1:

clean funktioniert so noch nicht, siehe unten.

Ich vermute aber, dass wir nicht wirklich drumherumkommen den 950 nochmal deutlicher zu trennen. Bei getLifeSpan ist schon das erste größere Problem, da hier auch das Format des bodys anders ist und nicht nur die Bezeichnung. Der 950 erwartet "body": {"data": ["brush"]} statt "body":{"data":{"type":"brush"}} Die Antwort ist sonst "body":{"code":10000,"msg":"data content has nothing"}

Das clean Kommando gibt auch nur folgenden Fehler zurück: "body":{"code":20011,"msg":"get act error"} Der Aufruf beinhaltet derzeit: data":{"clean":{"type":"auto","speed":"standard","act":"s"} Erwartet wird hier für den 950 aber: "data": {"act": "start","type": "auto"} Also auch hier wieder ein Strukturunterschied zusätzlich zum unterschiedlichen Begriff im act.

Ja das geht ganz klar in die Richtung, dass wie verschiedenen Modell-Varianten besser trennen müssen. Als ich damit angefangen hatte bin ich davon ausgegangen, dass man nur zwischen XMPP und MQTT basierten Geräten unterscheiden müsste, aber das ist ganz klar wesentlich komplizierter, da es im Detail auch pro Modell Unterschiede gibt in der API gibt, welche beim Ozmo 950 noch mal weitreichender sind. Ich gehe mal davon aus, dass es sich um eine neue Gerätegeneration handelt.

Ich mache jetzt erstmal ein wenig Theorie-Arbeit und eine Liste für den 950 mit cmdName und zugehörigem body für das senden eines Kommandos responses und dazugehörigem body für das Verarbeiten einer eingehenden Nachricht Dann versuche ich mal das irgendwie übersichtlich auszulagern.

Ein positives Ergebnis habe ich für heute dann aber doch geschaffen: Ich hab aber einen Pull Request gestellt mit der Korrektur der JSON response-Erkennung. Die funktioniert nun :-) Da sind auch noch ein paar andere Änderungen dabei (water level und batterystatus), die du bitte einmal prüfen müsstest (siehe Beschreibung im Pull Request)..

Ich schaue mir das heute Abend dann mal genauer an. An dieser Stelle müssen wir aufpassen, dass wir nicht die Kompatibilät zu den Geräten verlieren, welche bisher schon funktionieren (z.B. Deebot Slim 2).

mrbungle64 commented 4 years ago

Das response-handling funktioniert so auch nicht gut für den 950. Bisher wird auf topic.name geprüft. Das ist aber für den 950 undefined. Daher greift im Moment nur die _body_data_to_command, die auf Basis des body-Inhalts auf die Nachricht schließt. Das ist nicht so fein.

Ja damit war ich natürlich auch nicht zufrieden ... Das ist so entstanden, weil ich ja immer nur auf die Rückmeldungen von Besitzern der entsprechenden Geräte reagieren konnte. Das ändert sich ja jetzt zum Glück durch deine aktive Mitarbeit :+1:

Als topic kommt z.B. sowas zurück: iot/atr/onCleanInfo/[...] Damit lassen sich die Nachrichten gut unterscheiden.

ok gut

Ich habe mal eine Übersicht angefangen, als Excel im Anhang 950_API.xlsx

Sehr gut :+1:

boriswerner commented 4 years ago

Ja das geht ganz klar in die Richtung, dass wie verschiedenen Modell-Varianten besser trennen müssen. Als ich damit angefangen hatte bin ich davon ausgegangen, dass man nur zwischen XMPP und MQTT basierten Geräten unterscheiden müsste, aber das ist ganz klar wesentlich komplizierter, da es im Detail auch pro Modell Unterschiede gibt in der API gibt, welche beim Ozmo 950 noch mal weitreichender sind. Ich gehe mal davon aus, dass es sich um eine neue Gerätegeneration handelt.

Meine Idee wäre die VacBot-Klasse aus der index.js in die EcovacsMQTT.js auszulagern und auch direkt in eine EcovacsMQTT_XML.js und EcovacsMQTT_JSON.js zu trennen.

Die VacBotCommands müssten dann so abstrahiert werden, dass sie alle Modelle abdecken, die konkrete Implementierung dann aber in der jeweiligen Modell-Library passiert.

So besteht zwar die Gefahr, dass man einigen Code doppelt hat, aber die ganzen Fallunterscheidungen machen es zum einen recht unübersichtlich, zum anderen auch fehleranfälliger. SO könnte man einmal in der index.js die Unterscheidung machen und gut ist. Außerdem gibt es ja prinzipiell auch die Möglichkeit mehrere Bots zu verwalten. Btw. welches Modell / welche Modelle hast du nochmal? Einen 930 (MQTT_XML) und einen XMPP (Deebot Slim2) oder? Nutzen die die gleiche App und wie machst du die Aufrufe bei zwei Geräten? Der 950 nutzt die EcoVacs Home App.

Ich bin ja eigentlich schon ganz heiß darauf mit den Karten und Koordinaten was zu machen, aber erstmal die Basics ;-P

mrbungle64 commented 4 years ago

Ja das geht ganz klar in die Richtung, dass wie verschiedenen Modell-Varianten besser trennen müssen. Als ich damit angefangen hatte bin ich davon ausgegangen, dass man nur zwischen XMPP und MQTT basierten Geräten unterscheiden müsste, aber das ist ganz klar wesentlich komplizierter, da es im Detail auch pro Modell Unterschiede gibt in der API gibt, welche beim Ozmo 950 noch mal weitreichender sind. Ich gehe mal davon aus, dass es sich um eine neue Gerätegeneration handelt.

Meine Idee wäre die VacBot-Klasse aus der index.js in die EcovacsMQTT.js auszulagern und auch direkt in eine EcovacsMQTT_XML.js und EcovacsMQTT_JSON.js zu trennen.

Die VacBotCommands müssten dann so abstrahiert werden, dass sie alle Modelle abdecken, die konkrete Implementierung dann aber in der jeweiligen Modell-Library passiert.

Ja so ungefähr wollte ich das auch gerade vorschlagen :+1:

So besteht zwar die Gefahr, dass man einigen Code doppelt hat, aber die ganzen Fallunterscheidungen machen es zum einen recht unübersichtlich, zum anderen auch fehleranfälliger. SO könnte man einmal in der index.js die Unterscheidung machen und gut ist. Außerdem gibt es ja prinzipiell auch die Möglichkeit mehrere Bots zu verwalten.

Die Verwaltung von mehreren Bots hatte ich bisher im ioBroker über die Adapter-Instanzen abgebildet - das funktioniert bei meinen Geräten auch soweit. Muss man mal schauen was da perspektivisch gesehen besser wäre.

Btw. welches Modell / welche Modelle hast du nochmal? Einen 930 (MQTT_XML) und einen XMPP (Deebot Slim2) oder? Nutzen die die gleiche App und wie machst du die Aufrufe bei zwei Geräten? Der 950 nutzt die EcoVacs Home App.

Beides leider XMPP basierte Geräte. Daher habe ich bisher ja was den MQTT Teil betrifft "trocken" bzw. "blind" entwickelt.

Für beide benutze ich auch die Home App (Android) - aktuell in der Version 1.3.1. Dort sind beide Geräte eingebunden.

In ioBroker Instanziiere das VacBot Objekt mit dem entsprechenden device, welches in der Adapter Instanz eingestellt ist.

const vacuum = devices[this.deviceNumber];
...
this.vacbot = new VacBot(..., vacuum, ...);
...

Ich bin ja eigentlich schon ganz heiß darauf mit den Karten und Koordinaten was zu machen, aber erstmal die Basics ;-P

mrbungle64 commented 4 years ago

Ja das geht ganz klar in die Richtung, dass wie verschiedenen Modell-Varianten besser trennen müssen. Als ich damit angefangen hatte bin ich davon ausgegangen, dass man nur zwischen XMPP und MQTT basierten Geräten unterscheiden müsste, aber das ist ganz klar wesentlich komplizierter, da es im Detail auch pro Modell Unterschiede gibt in der API gibt, welche beim Ozmo 950 noch mal weitreichender sind. Ich gehe mal davon aus, dass es sich um eine neue Gerätegeneration handelt.

Meine Idee wäre die VacBot-Klasse aus der index.js in die EcovacsMQTT.js auszulagern und auch direkt in eine EcovacsMQTT_XML.js und EcovacsMQTT_JSON.js zu trennen.

Die VacBotCommands müssten dann so abstrahiert werden, dass sie alle Modelle abdecken, die konkrete Implementierung dann aber in der jeweiligen Modell-Library passiert.

Möchtest Du vielleicht mal mit der EcovacsMQTT_JSON.js beginnen? Die kann man für den Anfang ja erstmal über die Unterscheidung per isOzmo950() einbinden, anstatt der EcovacsMQTT.js.

Irgendwie so in der Art (index.js):

    if (!this.useMqtt) {
      ....
    } else {
      ...
      let jsFile = 'ecovacsMQTT'; // Später dann ecovacsMQTT_XML
      if (this.isOzmo950()) jsFile = 'ecovacsMQTT_JSON';
      const EcovacsMQTT = require('./library/' + jsFile + '.js');
      this.ecovacs = new EcovacsMQTT(this, user, hostname, resource, secret, continent, vacuum, server_address);
    }
boriswerner commented 4 years ago

Aber dann ist es auf jeden Fall umso besser alles zu trennen. So laufen wir auch nicht Gefahr was für ein Modell kaputtzumachen, welches wir garnicht selbst testen können. Wir sollten uns dann nur über die abstrakten Funktionen und States einig werden, die nach außen hin angeboten werden (die bisher vorhandenen sind ja quasi gesetzt) und wie wir dann mit nicht unterstützten Funktionen/States bei einem Modell umgehen.

Das sollten wir wohl in einem neuen Branch entwickeln, da es doch ein recht großer Umbau ist, oder? Ich bin noch recht neu im git-Umfeld, aber wir sollten das bestehende auf jeden Fall sichern (oder ein Release?)

Ich bin für heute mit meiner "Freizeit" hierfür durch und komme wahrscheinlich erst am Sonntag wieder dazu etwas produktiv am Code zu machen. Dann kann ich mich aber auch gerne um die Abstraktion und die Auslagerung kümmern.

Möchtest Du vielleicht mal mit der EcovacsMQTT_JSON.js beginnen? Die kann man für den Anfang ja erstmal über die Unterscheidung per isOzmo950() einbinden, anstatt der EcovacsMQTT.js.

Wieder zu lange getippt... das würde ich dann am Sonntag angehen.

mrbungle64 commented 4 years ago

Aber dann ist es auf jeden Fall umso besser alles zu trennen. So laufen wir auch nicht Gefahr was für ein Modell kaputtzumachen, welches wir garnicht selbst testen können. Wir sollten uns dann nur über die abstrakten Funktionen und States einig werden, die nach außen hin angeboten werden (die bisher vorhandenen sind ja quasi gesetzt) und wie wir dann mit nicht unterstützten Funktionen/States bei einem Modell umgehen.

Das sollten wir wohl in einem neuen Branch entwickeln, da es doch ein recht großer Umbau ist, oder? Ich bin noch recht neu im git-Umfeld, aber wir sollten das bestehende auf jeden Fall sichern (oder ein Release?)

Ich bin für heute mit meiner "Freizeit" hierfür durch und komme wahrscheinlich erst am Sonntag wieder dazu etwas produktiv am Code zu machen. Dann kann ich mich aber auch gerne um die Abstraktion und die Auslagerung kümmern.

Möchtest Du vielleicht mal mit der EcovacsMQTT_JSON.js beginnen? Die kann man für den Anfang ja erstmal über die Unterscheidung per isOzmo950() einbinden, anstatt der EcovacsMQTT.js.

Wieder zu lange getippt... das würde ich dann am Sonntag angehen.

ok, alles klar. Dann befasse ich mich heute Abend erst mal mit Deinem Pull Request und teste das mit meinen Geräten. Danach überlege ich mir wie wir am besten weiter vorgehen könnten

(sorry, hatte zuerst aus Versehen Deinen Kommentar editiert)

capitaenz commented 4 years ago

Nur mal eine kurze Zwischenfrage: Was sagt Ecovac denn zu einem ioBroker Adapter? Mal nach Hilfe bzw. Doku gefragt?

gigasi commented 4 years ago

Hallo zusammen👋 Erstmal @mrbungle64 und @boriswerner ihr seid der Wahnsinn!! Das ihr beide euch da so reinkniet, VIELEN DANK 🙏

@capitaenz das Problem ist Ecovac gibt keine Daten in Bezug Scripten raus nur für Größe Firmen wie Amazon für ALEXA sonst hat man keine Chance.

boriswerner commented 4 years ago

Hab doch nochmal etwas Zeit gefunden und angefangen, bin dann aber schnell zu den Abstraktionen gekommen. Wie wäre es mit sowas:

const dictionaryToEcovacs = { 
    "COMPONENT_MAIN_BRUSH"  :  {"FUNCTION": "COMPONENT", "ECOVACS_XMPP": "main_brush", "ECOVACS_JSON": "brush", "ABSTRACTION": "main_brush", "en": "Main Brush", "de": "Hauptbürste"},
    "COMPONENT_SIDE_BRUSH"  :  {"FUNCTION": "COMPONENT", "ECOVACS_XMPP": "side_brush", "ECOVACS_JSON": "sideBrush", "ABSTRACTION": "side_brush", "en": "Side Brush", "de": "Seitenbürste"},
    "COMPONENT_FILTER"  :  {"FUNCTION": "COMPONENT", "ECOVACS_XMPP": "filter", "ECOVACS_JSON": "heap", "ABSTRACTION": "filter", "en": "Filter", "de": "Filter"},
    "FAN_SPEED_QUIET"  :  {"FUNCTION": "FAN_SPEED", "ECOVACS_XMPP": undefined, "ECOVACS_JSON": "1000", "ABSTRACTION": "quiet", "en": "Quiet", "de": "Leise"},
    "FAN_SPEED_NORMAL"  :  {"FUNCTION": "FAN_SPEED", "ECOVACS_XMPP": "standard", "ECOVACS_JSON": "0", "ABSTRACTION": "normal", "en": "Normal", "de": "Standard"},
    "FAN_SPEED_MAX"  :  {"FUNCTION": "FAN_SPEED", "ECOVACS_XMPP": undefined, "ECOVACS_JSON": "1", "ABSTRACTION": "max", "en": "Max", "de": "Maximal"},
    "FAN_SPEED_MAXPLUS"  :  {"FUNCTION": "FAN_SPEED", "ECOVACS_XMPP": "notsupported", "ECOVACS_JSON": "2", "ABSTRACTION": "max+", "en": "Max+", "de": "Maximal+"},
    "CMD_GET_CLEANSTATE"  :  {"FUNCTION": "COMMAND", "ECOVACS_XMPP": "GetBatteryInfo", "ECOVACS_JSON": "getBattery", "ABSTRACTION": "GetBatteryInfo", "en": "Update battery status", "de": "Aktualisiere Batteriestand"},
    "CMD_CLEAN"  :  {"FUNCTION": "COMMAND", "ECOVACS_XMPP": "Clean", "ECOVACS_JSON": "clean", "ABSTRACTION": "Clean", "en": "Start cleaning", "de": "Starte Reinigung"}
};

let dictionaryFromECOVACS_JSONToAbstraction = {};
for (let entry in dictionaryToEcovacs) {
    if (!dictionaryFromECOVACS_JSONToAbstraction.hasOwnProperty(dictionaryToEcovacs[entry]["FUNCTION"])) {
        dictionaryFromECOVACS_JSONToAbstraction[ dictionaryToEcovacs[entry]["FUNCTION"] ]  = {default: "default"};
    }
    dictionaryFromECOVACS_JSONToAbstraction[ dictionaryToEcovacs[entry]["FUNCTION"] ] [dictionaryToEcovacs[entry]["ECOVACS_JSON"]] = entry;
}
//console.log(JSON.stringify(dictionaryFromECOVACS_JSONToAbstraction));
console.log("-----");
console.log("get values for sending to Ecovacs");
console.log("-----");
console.log(dictionaryToEcovacs["FAN_SPEED_QUIET"]["ECOVACS_XMPP"]);
console.log(dictionaryToEcovacs["FAN_SPEED_QUIET"]["ECOVACS_JSON"]);
console.log(dictionaryToEcovacs["FAN_SPEED_QUIET"]["ABSTRACTION"]);
console.log(dictionaryToEcovacs["FAN_SPEED_NORMAL"]["ECOVACS_XMPP"]);
console.log(dictionaryToEcovacs["CMD_GET_CLEANSTATE"]["ECOVACS_XMPP"]);
console.log(dictionaryToEcovacs["CMD_GET_CLEANSTATE"]["ECOVACS_JSON"]);

console.log("-----");
console.log("get values for handling responses from Ecovacs");
console.log("-----");
console.log(dictionaryFromECOVACS_JSONToAbstraction["FAN_SPEED"]["1000"]);
console.log(dictionaryFromECOVACS_JSONToAbstraction["COMPONENT"]["brush"]);

Ergibt

-----
get values for sending to Ecovacs
-----
undefined
1000
quiet
standard
GetBatteryInfo
getBattery
-----
get values for handling responses from Ecovacs
-----
FAN_SPEED_QUIET
COMPONENT_MAIN_BRUSH

So muss man nur einmal an zentraler Stelle die abstrakte API und die Übersetzung pflegen, Zusammengesetzt wird es dann in den jeweiligen Funktionen der spezifischen API. Vielleicht kann man sogar die Übersetzungen der Werte für den ioBroker mit einpflegen (deswegen die "de" und "en" Ausprägungen. Wie das genau aussehen kann weiß ich aber auch nicht, hab erst einen sehr rudimentären Adapter für ioBroker geschrieben...)

mrbungle64 commented 4 years ago

Hab doch nochmal etwas Zeit gefunden und angefangen, bin dann aber schnell zu den Abstraktionen gekommen. Wie wäre es mit sowas:

const dictionaryToEcovacs = { 
    "COMPONENT_MAIN_BRUSH"  :  {"FUNCTION": "COMPONENT", "ECOVACS_XMPP": "main_brush", "ECOVACS_JSON": "brush", "ABSTRACTION": "main_brush", "en": "Main Brush", "de": "Hauptbürste"},
    "COMPONENT_SIDE_BRUSH"  :  {"FUNCTION": "COMPONENT", "ECOVACS_XMPP": "side_brush", "ECOVACS_JSON": "sideBrush", "ABSTRACTION": "side_brush", "en": "Side Brush", "de": "Seitenbürste"},
    "COMPONENT_FILTER"  :  {"FUNCTION": "COMPONENT", "ECOVACS_XMPP": "filter", "ECOVACS_JSON": "heap", "ABSTRACTION": "filter", "en": "Filter", "de": "Filter"},
    "FAN_SPEED_QUIET"  :  {"FUNCTION": "FAN_SPEED", "ECOVACS_XMPP": undefined, "ECOVACS_JSON": "1000", "ABSTRACTION": "quiet", "en": "Quiet", "de": "Leise"},
    "FAN_SPEED_NORMAL"  :  {"FUNCTION": "FAN_SPEED", "ECOVACS_XMPP": "standard", "ECOVACS_JSON": "0", "ABSTRACTION": "normal", "en": "Normal", "de": "Standard"},
    "FAN_SPEED_MAX"  :  {"FUNCTION": "FAN_SPEED", "ECOVACS_XMPP": undefined, "ECOVACS_JSON": "1", "ABSTRACTION": "max", "en": "Max", "de": "Maximal"},
    "FAN_SPEED_MAXPLUS"  :  {"FUNCTION": "FAN_SPEED", "ECOVACS_XMPP": "notsupported", "ECOVACS_JSON": "2", "ABSTRACTION": "max+", "en": "Max+", "de": "Maximal+"},
    "CMD_GET_CLEANSTATE"  :  {"FUNCTION": "COMMAND", "ECOVACS_XMPP": "GetBatteryInfo", "ECOVACS_JSON": "getBattery", "ABSTRACTION": "GetBatteryInfo", "en": "Update battery status", "de": "Aktualisiere Batteriestand"},
    "CMD_CLEAN"  :  {"FUNCTION": "COMMAND", "ECOVACS_XMPP": "Clean", "ECOVACS_JSON": "clean", "ABSTRACTION": "Clean", "en": "Start cleaning", "de": "Starte Reinigung"}
};

let dictionaryFromECOVACS_JSONToAbstraction = {};
for (let entry in dictionaryToEcovacs) {
    if (!dictionaryFromECOVACS_JSONToAbstraction.hasOwnProperty(dictionaryToEcovacs[entry]["FUNCTION"])) {
        dictionaryFromECOVACS_JSONToAbstraction[ dictionaryToEcovacs[entry]["FUNCTION"] ]  = {default: "default"};
    }
    dictionaryFromECOVACS_JSONToAbstraction[ dictionaryToEcovacs[entry]["FUNCTION"] ] [dictionaryToEcovacs[entry]["ECOVACS_JSON"]] = entry;
}
//console.log(JSON.stringify(dictionaryFromECOVACS_JSONToAbstraction));
console.log("-----");
console.log("get values for sending to Ecovacs");
console.log("-----");
console.log(dictionaryToEcovacs["FAN_SPEED_QUIET"]["ECOVACS_XMPP"]);
console.log(dictionaryToEcovacs["FAN_SPEED_QUIET"]["ECOVACS_JSON"]);
console.log(dictionaryToEcovacs["FAN_SPEED_QUIET"]["ABSTRACTION"]);
console.log(dictionaryToEcovacs["FAN_SPEED_NORMAL"]["ECOVACS_XMPP"]);
console.log(dictionaryToEcovacs["CMD_GET_CLEANSTATE"]["ECOVACS_XMPP"]);
console.log(dictionaryToEcovacs["CMD_GET_CLEANSTATE"]["ECOVACS_JSON"]);

console.log("-----");
console.log("get values for handling responses from Ecovacs");
console.log("-----");
console.log(dictionaryFromECOVACS_JSONToAbstraction["FAN_SPEED"]["1000"]);
console.log(dictionaryFromECOVACS_JSONToAbstraction["COMPONENT"]["brush"]);

Ergibt

-----
get values for sending to Ecovacs
-----
undefined
1000
quiet
standard
GetBatteryInfo
getBattery
-----
get values for handling responses from Ecovacs
-----
FAN_SPEED_QUIET
COMPONENT_MAIN_BRUSH

So muss man nur einmal an zentraler Stelle die abstrakte API und die Übersetzung pflegen, Zusammengesetzt wird es dann in den jeweiligen Funktionen der spezifischen API. Vielleicht kann man sogar die Übersetzungen der Werte für den ioBroker mit einpflegen (deswegen die "de" und "en" Ausprägungen. Wie das genau aussehen kann weiß ich aber auch nicht, hab erst einen sehr rudimentären Adapter für ioBroker geschrieben...)

Grundsätzlich eine gute Idee. Man müsste allerdings erst prüfen, welche Varianten es (wirklich) gibt. Meine Erfahrung ist, dass es auch Unterschiede innerhalb der Protokoll-Varianten im Detail gibt. Wir wissen ja aufgrund fehlender API Doku nicht, was Ecovacs da noch für Überraschungen zu bieten hat ;)

boriswerner commented 4 years ago

Achso, ich dachte es gäbe nur die Varianten XMPP, MQTT mit XML responses und halt den 950 mit MQTT mit JSON responses... Dann wohl doch eine Unterscheidung nach DeviceID mit einem "Vorbildmodell"je nach Protokoll-Typ auf das dann erstmal entwickelt wird. Sobald man dann Abweichungen hat müsste man eine neue Klasse erstellen, die von der Vorbild Klasse erbt und dann die entsprechenden Methoden überschreibt?!?

mrbungle64 commented 4 years ago

Achso, ich dachte es gäbe nur die Varianten XMPP, MQTT mit XML responses und halt den 950 mit MQTT mit JSON responses...

Ja eigentlich schon, aber ich bin inzwischen vorsichtig geworden ;)

Dann wohl doch eine Unterscheidung nach DeviceID mit einem "Vorbildmodell"je nach Protokoll-Typ auf das dann erstmal entwickelt wird. Sobald man dann Abweichungen hat müsste man eine neue Klasse erstellen, die von der Vorbild Klasse erbt und dann die entsprechenden Methoden überschreibt?!?

Eine Möglichkeit wäre noch Abweichungen vom Vorbildmodell in der ecovacsConstants.js zu intergrieren. Irgendwie hier (Beispiel):

    "115": {
        "name": "DEEBOT OZMO/PRO 930 Series",
        "main_brush": true,
        "spot_area": true,
        "custom_area": true,
        "mopping_system": true,
        "voice_report": true,
        'single_room': false,
    }

Falls überhaupt notwendig ;)

mrbungle64 commented 4 years ago

@boriswerner

Mal was anderes: Funktioniert mit dem aktuellem Stand genug für den Ozmo 950, dass wir mal einen Release auf npm wagen können? Dann stelle ich mal eine Version vom ioBroker Adapter auf Github bereit, welcher auf dieser Version basiert.

Dein Pull request ist ja gemerged und ich teste das gleich noch mal mit meinen Geräten und korrigiere das noch "schnell" mit battery_info und water_level.

boriswerner commented 4 years ago

@boriswerner

Mal was anderes: Funktioniert mit dem aktuellem Stand genug für den Ozmo 950, dass wir mal einen Release auf npm wagen können? Dann stelle ich mal eine Version vom ioBroker Adapter auf Github bereit, welcher auf dieser Version basiert.

Dein Pull request ist ja gemerged und ich teste das gleich noch mal mit meinen Geräten und korrigiere das noch "schnell" mit battery_info und water_level.

Naja. Bisher nur so ein paar der Get Methoden... Müsste ich bei Gelegenheit nochmal schauen, was alles geht. Aber wenn das nicht viel Aufwand ist, mach doch gerne, dann installier ich den Adapter auch endlich Mal und kann testen :-)

mrbungle64 commented 4 years ago

@boriswerner

ok, Release 0.3.5 vom ioBroker Adapter ist da :D

Ich bin gespannt :)

boriswerner commented 4 years ago

Kreuzchen für die Adapter Readme für den 950: Buttons and control playSound

Info and status battery chargestatus (obwohl Meldung im Log, s.u.)

Info zum waterLevel funktioniert leider nicht (hätte ich eigentlich erwartet... naja) Die device-Infos und das protocol sind leider auch nicht gefüllt, siehe Bild im Anhang.

Im Log bekomme ich die Info-Meldungen Unhandled chargestatus: docked Unhandled cleanstatus: null

image

Vielleicht sollte ich mit einem quick & dirty Change doch schonmal die clean und Charge Befehle einbauen um die Leute bei Laune zu halten ;-) Dann ist der Druck für das refactoring auch nicht so hoch :-p

mrbungle64 commented 4 years ago

@boriswerner

Die device-Infos und das protocol sind leider auch nicht gefüllt, siehe Bild im Anhang.

Ändere mal die Rolle von text auf value. Dann sollten die Felder nach einem Neustart vom Adapter befüllt werden. Ich fixe das aber auch gleich mal im Code.

Bzw. jetzt gerade hat auch ein Neustart ohne Ändern der Rolle geholfen.

mrbungle64 commented 4 years ago

Vielleicht sollte ich mit einem quick & dirty Change doch schonmal die clean und Charge Befehle einbauen um die Leute bei Laune zu halten ;-) Dann ist der Druck für das refactoring auch nicht so hoch :-p

Ja kann man machen :D

mrbungle64 commented 4 years ago

@boriswerner

Die device-Infos und das protocol sind leider auch nicht gefüllt, siehe Bild im Anhang.

Ändere mal die Rolle von text auf value. Dann sollten die Felder nach einem Neustart vom Adapter befüllt werden. Ich fixe das aber auch gleich mal im Code.

Bzw. jetzt gerade hat auch ein Neustart ohne Ändern der Rolle geholfen.

Hab den Fehler gefunden ... Einfach neu starten - dann sollte das befüllt sein.

Ich fixe den Bug dann mal jetzt ... ^^

boriswerner commented 4 years ago

Ich habe einen Pull Request erstellt und die Basisaufrufe Clean und Charge funktionieren jetzt in der Library. Im iobroker hab ich noch nicht getestet.

Hab den Fehler gefunden ... Einfach neu starten - dann sollte das befüllt sein.

Nun werden auch deviceClass, deviceName und communicationProtocol angezeigt 👍

gigasi commented 4 years ago

Ich würde ja gerne mithelfen aber ich versteh nur noch Bahnhof 😅 hilft es euch noch wenn ich teste?

boriswerner commented 4 years ago

Ich sehe jetzt übrigens erst, dass die Diskussion hier im Adapter und nicht in der library stattfindet :-D ist vielleicht wirklich nicht der richtige Ort für die technischen Diskussionen.

@gigasi Im Moment ist halt noch sehr viel Analyse und Prototyping für den 950 und noch nicht so viel zu testen. Wenn @mrbungle64 die neue Version nochmal einstellt könntest du zumindest Mal schauen, ob das clean und Charge aus dem iobroker funktioniert. Über die library funktioniert es bei mir. Im Moment geht es erst Mal darum die bestehenden basics aus dem Adapter zu implementieren. Aber da ist natürlich auch jeder zusätzliche Test sehr hilfreich. So richtig spannend wird es aber sicher erst wieder, wenn es dann an neue Funktionen geht (ich brenne ja darauf über den iobroker z.b. Sperrzonen zu aktivieren und zu deaktivieren. Die App lässt ja nur löschen und neu erstellen zu)

B0F1B0 commented 4 years ago

@mrbungle64 , @all

i have an deebot ozmo 950 and installed iobroker-adapter ecovacs-deebot 0.3.5 and get the following error message in log:

ecovacs-deebot Error-Message

if u need any other information / logs / etc pls. let me know.

""THERE WE HAVE THE SALAD""

B0F1B0

mrbungle64 commented 4 years ago

Ich sehe jetzt übrigens erst, dass die Diskussion hier im Adapter und nicht in der library stattfindet :-D ist vielleicht wirklich nicht der richtige Ort für die technischen Diskussionen.

Ja richtig - das wollte ich auch mal ansprechen :+1: Da es richtig produktiv war wollte ich es nicht unterbrechen.

Ich würde vorschlagen, dass wir zum Zeitpunkt wo wir den großen Umbau starten in der Library weiter machen und diesen Issue (mit inzwischen weit über 150 Kommentaren) mal löschen und einen neuen öffnen.

mrbungle64 commented 4 years ago

Ich habe einen Pull Request erstellt und die Basisaufrufe Clean und Charge funktionieren jetzt in der Library. Im iobroker hab ich noch nicht getestet.

@boriswerner

Ich habe mir den Pull request angeschaut und eigentlich müssten wir ja nur die Kommandos für den 950 übersetzen (in der ecovacsConstants.js).

Ich würde den Teil aus der ecovacsConstants.js aus Deinem Pull request mal einbauen und dann schauen wir mal, ob wir uns den duplizierten Code erst mal sparen können.

Wäre das ok für Dich?

Hab den Fehler gefunden ... Einfach neu starten - dann sollte das befüllt sein.

Nun werden auch deviceClass, deviceName und communicationProtocol angezeigt

:+1:

boriswerner commented 4 years ago

@B0F1B0 I will try to have a look at that tomorrow. Or do you have an Idea, @mrbungle64 ?

@mrbungle64 ich wollte nichts bestehendes kaputt machen und hab es deswegen erstmal komplett getrennt. Quick & Dirty eben. So kann ich auf jeden Fall ganz sicher daran auch größere Änderungen machen und testen, ohne dass es Auswirkungen auf andere Modelle haben könnte... Da ist glaube ich nämlich noch mehr notwendig um das einigermaßen zum Laufen zu bekommen.

mrbungle64 commented 4 years ago

@B0F1B0 I will try to have a look at that tomorrow. Or do you have an Idea, @mrbungle64 ?

@boriswerner Not yet. I'll have a look at that later.

@B0F1B0 Does the error occur reproducibly?

@mrbungle64 ich wollte nichts bestehendes kaputt machen und hab es deswegen erstmal komplett getrennt. Quick & Dirty eben. So kann ich auf jeden Fall ganz sicher daran auch größere Änderungen machen und testen, ohne dass es Auswirkungen auf andere Modelle haben könnte... Da ist glaube ich nämlich noch mehr notwendig um das einigermaßen zum Laufen zu bekommen.

Ja, verstehe. Ich denke aber, dass folgendes auch funktionieren würde:

send_command(action, recipient) {
        if (this.bot.isOzmo950()) {
            if (constants.COMMAND_TO_OZMO950[action.name]) {
                action.name = constants.COMMAND_TO_OZMO950[action.name];
            }
            if (constants.CLEAN_MODE_TO_OZMO950[action.args['type']]) {
                action.args['type'] = constants.CLEAN_MODE_TO_OZMO950[action.args['type']];
            }
            if (constants.FAN_SPEED_TO_OZMO950[action.args['speed']]) {
                action.args['speed'] = constants.FAN_SPEED_TO_OZMO950[action.args['speed']];
            }
            if (constants.CLEAN_ACTION_TO_OZMO950[action.args['act']]) {
                action.args['act'] = constants.CLEAN_ACTION_TO_OZMO950[action.args['act']];
            }
        }
        ...
exports.CLEAN_MODE_TO_OZMO950 = {
    'SpotArea': 'spotArea'
};

...

exports.CLEAN_ACTION_TO_OZMO950 = {
    's': 'start',
    'p': 'pause',
    'r': 'resume',
    'h': 'stop'
};

...

exports.FAN_SPEED_TO_OZMO950 = {
    'standard': '0',
    'strong': '1'
};

...

exports.CHARGE_MODE_TO_OZMO950 = {
    'go': 'return',
    'Going': 'returning',
    'SlotCharging': 'charging',
    'Idle': 'idle'
};

Also quasi nach der Übersetzung für Ecovacs noch mal für den 950 übersetzen :D

Und halt immer nur das was notwendig ist (s. CLEAN_MODE_TO_OZMO950).

... und anschließend dann noch enstprechend die ...FROM_ECOVACS Übersetzungen

mrbungle64 commented 4 years ago

@mrbungle64 , @ALL

i have an deebot ozmo 950 and installed iobroker-adapter ecovacs-deebot 0.3.5 and get the following error message in log:

ecovacs-deebot Error-Message

if u need any other information / logs / etc pls. let me know.

""THERE WE HAVE THE SALAD""

B0F1B0

@B0F1B0 If the error occurs reproducibly can you please create a new issue so that we can focus on this specific bug? Thanks in advance :)

mrbungle64 commented 4 years ago

@boriswerner, @gigasi, @krobipd, @rebel1985, @B0F1B0, @AudidriverA4, @capitaenz

Die Version 0.3.6 steht bereit und kann über Github installiert werden. Für alle Rückmeldungen bitte einen neuen Issue anlegen, damit wir diesen hier mal schließen können :)

Version 0.3.6 is released and can be installed via Github. For all feedback please create a new issue, so we can close this issue :)

B0F1B0 commented 4 years ago

@mrbungle64 ich habe ein neues issue https://github.com/mrbungle64/ioBroker.ecovacs-deebot/issues/10 dazu aufgemacht, konnte es aber auch gleich wieder schließen, da es an einer zu alten Node.JS Version lag. (alt 8.3 neu 10.x) Zu Info: es kommen jetzt zwar keine Fehlermeldungen mehr im Log, es passiert aber auch nichts wenn man auf die Buttons unter Command klickt.

""THERE WE HAVE THE SALAD ""

B0F1B0

mrbungle64 commented 4 years ago

@mrbungle64 ich habe ein neues issue

10

dazu aufgemacht, konnte es aber auch gleich wieder schließen, da es an einer zu alten Node.JS Version lag. (alt 8.3 neu 10.x) Zu Info: es kommen jetzt zwar keine Fehlermeldungen mehr im Log, es passiert aber auch nichts wenn man auf die Buttons unter Command klickt.

""THERE WE HAVE THE SALAD ""

B0F1B0

@B0F1B0 ok, danke für die Rückmeldung.

Ist der Adapter bereits vollständig connected? Kommen Werte unter info wie z.B. battery, deviceName oder deviceClass?

B0F1B0 commented 4 years ago

@mrbungle64 sorry, my fault.....

ja es funktionieren fast alle commands (pause geht nicht) kann ich aber erst morgen richtig testen....

mrbungle64 commented 4 years ago

@mrbungle64 sorry, my fault.....

ja es funktionieren fast alle commands (pause geht nicht) kann ich aber erst morgen richtig testen....

ok, das hört sich doch gar nicht so schlecht an :+1: