NEWS
Status, Steuerung und Automatisierung Robomow (Rasenmähroboter)
-
Hey All,
ich dachte mir ich poste auch mal eins der Skripte die ich im Einsatz habe.
Ich habe einen Rasenmäh-Roboter von Robomow und ich monitore den Status des Mähers und versuche auch zu erkennen wenn etwas komisch ist und er sich z.B. festgefahren hat. Weiterhin habe ich inzwischen die komplette Steuerung per ioBroker.
Das Status-Skript sollte für Robomow's an sich direkt funktionieren. Für andere Mäher muss man bestimmt die Stromverbrauchs-Erkenn-Schwellen anpassen.
Ob die Steuerungsskripte funktionieren denke ich eher nicht, aber die Logik ist generisch und mit einem identischen Tastenweisen Ansatz kann es auch da gehen.
1.) Status-Skript
Das Skript kann am Anfang über 5 Einstellungen Konfiguriert werden:
-
stateIdAnwesenheit: Die State-ID eines Sensors der sagt ob der Rasenmäher in der Ladestation ist oder nicht. Kann ein Tür/Fensterkontaktt oder was auch immer sein.
-
stateIdPower: Die State-ID wo der aktuelle Stromverbrauch der Ladestation ausgelesen werden kann, also z.B. ein Homematic-Mess-Schaltaktor o.ä.
-
instanceNotifyStatus: Die Instanz eines Notify-Adapters (z.B. pushover) die für alle allgemeinen Meldungen, Statuswechsel u.ä. genutzt werden soll. Darf auch leer sein.
-
instanceNotifyFehler: Die Instanz eines Notify-Adapters (z.B. pushover) die für die "Mäher ist zu lange weg (siehe nächster Wert). Ggf halt anders konfiguriert wegen anderem Alert-Ton oder so. Darf auch ler sein.
-
zeitAbwesenheitBisFehler: Anzahl ms bis zum Fehler. Bei mir 90 Minuten, weil er maximal 80 Minuten draussen ist wenn alles gut ist.
Das Skript legt in der aktuellen JavaScript-Instanz einen Datenpunkt "Robomow.Status" an wo dann der Status als String drinsteht:
-
Pause: Warten auf nächsten Einsatz, Fertig geladen
-
Mähen: Mähen
-
Unbekannt: Ist nicht anwesend und Stromverbrauch der Ladestation ist anders als erwartet …
-
Fehler: Hat sich wohl festgefahren
-
Laden: welch Überraschung, Er lädt
-
Fertig-Laden: Robomow macht am Ende der Haupt-Ladung immer noch ein Balance-Loading um die Speicherzellen auszugleichen.
Hier das Skript:
v20180101
var stateIdAnwesenheit = "hm-rpc.1.CUX0300004.1.STATE"; /*EG-Garten Robomow Anwesenheit:1.STATE*/ var stateIdPower = "hm-rpc.0.NEQ0117318.2.POWER"; /*EG-Garten Robomow:2.POWER*/ var stateIdAktiviert = "hm-rpc.0.NEQ0117318.1.STATE"; /*EG-Garten Robomow:1.STATE*/ var instanceNotifyStatus = "pushover.1"; var instanceNotifyFehler = "pushover.2"; // Initialisierung der States und Variablen var RobomowAnwesend = !!getState(stateIdAnwesenheit).val; var RobomowPower = parseFloat(getState(stateIdPower).val); var RobomowAktiviert = getState(stateIdAktiviert).val; var RobomowAktuellerStatus = getState("javascript." + instance + ".Robomow.Status").val; var RobomowLastPower = []; RobomowLastPower.push(RobomowPower); createState("javascript." +instance + ".Robomow.Status", {'type': 'string', 'read': true, 'write': false, 'role': 'text', 'def': 'Pause'}, function () { updateRobomowStatus(); }); function checkRobomowStatus(anwesend) { RobomowAnwesend = anwesend; RobomowLastPower = []; // Letzte Stromwerte löschen // Status aktualisieren updateRobomowStatus(); if (RobomowAktiviert) { // Zu lange Abwesend Check if (!RobomowAnwesend) { timeoutRobomowAbwesendZuLang = setTimeout(function () { RobomowAktuellerStatus = 'Fehler'; setState("javascript." + instance + ".Robomow.Status", RobomowAktuellerStatus, true); if (instanceNotifyFehler) { sendTo(instanceNotifyFehler, "send", { message: 'Robomow zu lange Abwesend - Festgefahren?', sound: "" }); } console.log("notify: Robomow zu lange Abwesend - Festgefahren?"); }, 5400000); } else { if (timeoutRobomowAbwesendZuLang) { clearTimeout(timeoutRobomowAbwesendZuLang); timeoutRobomowAbwesendZuLang = null; } } // Anwesenheitsänderung-Notify if (instanceNotifyStatus) { sendTo(instanceNotifyStatus, "send", { message: 'Anwesenheit Robomow: ' + RobomowAnwesend, sound: "" }); console.log("notify: Anwesenheit Robomow: " + RobomowAnwesend); } } } // Trigger Änderung Robomow-Anwesenheit var timeoutRobomowAbwesendZuLang; on({id: stateIdAnwesenheit, change: "ne"}, function (obj) { checkRobomowStatus(!!obj.state.val); }); checkRobomowStatus(!!getState(stateIdAnwesenheit).val); on({id: stateIdPower, change: "ne"}, function (obj) { RobomowAktiviert = obj.state.val; updateRobomowStatus(); }); on({id: stateIdAktiviert, change: "ne"}, function (obj) { RobomowPower = parseFloat(obj.state.val); if (RobomowLastPower.length > 11) { //RobomowLastPower = RobomowLastPower.slice(1); RobomowLastPower.shift(); } RobomowLastPower.push(RobomowPower); //if (RobomowAktuellerStatus === 'Fertig-Laden') console.log('New: ' + RobomowPower + ' : ' + JSON.stringify(RobomowLastPower)); updateRobomowStatus(); }); on({id: "javascript." + instance + ".Robomow.Status", change: "ne"}, function (obj) { var msg = 'Statuschange Robomow: ' + RobomowAktuellerStatus + ', ' + RobomowPower + 'W'; if (instanceNotifyStatus) { sendTo(instanceNotifyStatus, "send", { message: msg, sound: "" }); console.log("notify: " + msg); } }); /** * Ermittelt den Status des Robomow anhand des * Anwesenheitssensors und des Stromverbrauchs der Ladestation */ function updateRobomowStatus() { if (!RobomowAktiviert && RobomowAktuellerStatus !== "Deaktiviert") { RobomowAktuellerStatus = "Deaktiviert"; setState("javascript." + instance + ".Robomow.Status", RobomowAktuellerStatus, true); return; } if (RobomowAnwesend) { if (RobomowPower > 15) { // Anwesend && >=15W --> Laden if (RobomowAktuellerStatus !== 'Laden') { RobomowAktuellerStatus = 'Laden'; setState("javascript." + instance + ".Robomow.Status", RobomowAktuellerStatus, true); } } else if (RobomowLastPower.length > 4) { // erst mit mind. 5 Werten macht es Sinn var arr = RobomowLastPower.slice(0); arr.sort(function(a, b) { return a - b; }); var powerMin = arr[1]; var powerMax = arr[arr.length-2]; if (RobomowAktuellerStatus === 'Laden') { if (powerMin > 6.8) { // Kommen von Laden und jetzt zwischen 15W und 6.5W if (RobomowAktuellerStatus !== 'Fertig-Laden') { RobomowAktuellerStatus = 'Fertig-Laden'; setState("javascript." + instance + ".Robomow.Status", RobomowAktuellerStatus, true); } return; } else if (powerMax <= 6.8) { // Ansonsten kleiner/gleich als 6.8W, dann Pause (ohne Fertig-Laden) if (RobomowAktuellerStatus !== 'Pause') { RobomowAktuellerStatus = 'Pause'; setState("javascript." + instance + ".Robomow.Status", RobomowAktuellerStatus, true); } return; } } else if (RobomowAktuellerStatus !== 'Pause' && RobomowLastPower.length > 10) { // Verbrauch kleiner/gleich 6.8W, dann Pause //console.log(RobomowAktuellerStatus + ': powerMin=' + powerMin + ' / powerMax=' + powerMax); if (powerMax <= 6.8) { if (RobomowAktuellerStatus !== 'Pause') { RobomowAktuellerStatus = 'Pause'; setState("javascript." + instance + ".Robomow.Status", RobomowAktuellerStatus, true); } return; } } } } else { // Robomow Abwesend if (RobomowAktuellerStatus !== 'Fehler' && RobomowPower < 7) { // Abwesend && <7W --> Mähen if (RobomowAktuellerStatus !== 'Mähen') { RobomowAktuellerStatus = 'Mähen'; setState("javascript." + instance + ".Robomow.Status", RobomowAktuellerStatus, true); } } else if (RobomowAktuellerStatus !== 'Fehler' && RobomowLastPower.length > 10) { if (RobomowAktuellerStatus === 'Mähen' && RobomowPower > 15) { // Mähen aber >15W ... also Anwesenheitssensor komisch ... sendTo(instanceNotifyFehler, "send", { message: 'Robomow wieder in Ladestation, aber Sensor meldet keine Anwesenheit?!', sound: "" }); console.log("notify: Robomow wieder in Ladestation, aber Sensor meldet keine Anwesenheit?!"); RobomowAnwesend = true; RobomowLastPower = []; // Letzte Stromwerte löschen // Status aktualisieren setTimeout(updateRobomowStatus, 0); } } } }
2.) Generisches Steuerskript
Hier ist die Idee das der Mäher Tasten hat mit denen er bedient wird. Wenn man es schafft diese Tasten fernzubedienen (erstmal egal ob per Homematic oder anders) dann sind bestimmte Kommandos nur das Abspielen einer bestimmten Tastenreihenfolge. Genau das macht dieses Skript.
Das Skript hat am Anfang einige Einstellungen zur Konfiguration.
Das Skript legt in der aktuellen JavaScript-Instanz drei Datenpunkte ("Robomow.Command.Zone" und "Robomow.Command.Aktion" und "Robomow.InBetrieb") an mit dem das ganze dann bedient wird. In "Zone" schreibt man für die Aktionen die eine Zonenauswahl benötigen die anzusteuernde Zone rein. Mit einem setzen des States "Aktion" mit einem der definierten Aktionen aus dem Skript wird dieses ausgeführt. Beides mit "ack=false" setzen. Wenn die Aktion ausgeführt wurde, wird der "Aktion"-State mit "ack=true" bestätigt, sodass man darauf reagieren kann.
Nur wenn "InBetrieb" auf True steht reagiert die Steuerung. bedeutet: Per "InBetrieb" kann man die Steuerung aktivieren/deaktivieren.
Hier das Skript:
v20180101
`var RobomowButtons = { // Definition der Buttons 'STOP': true, 'HOME': true, 'RIGHT': true, 'LEFT': true, 'SETTINGS': false, 'OK': true }; var RobomowButtonController = { // Definition der ioBroker-States zum Triggern der einzelnen Tasten 'STOP': "hm-rpc.0.OEQ0208665.1.STATE"/*ED-Garten Robomow:1 Stop.STATE*/, 'HOME': "hm-rpc.0.OEQ0208665.3.STATE"/*ED-Garten Robomow:3 Home.STATE*/, 'RIGHT': "hm-rpc.0.OEQ0208665.5.STATE"/*ED-Garten Robomow:5 Mähen ohne Kante.STATE*/, 'LEFT': "hm-rpc.0.OEQ0208665.2.STATE"/*ED-Garten Robomow:2 Mähen mit Kante.STATE*/, 'SETTINGS': '', 'OK': "hm-rpc.0.OEQ0208665.4.STATE"/*ED-Garten Robomow:4 Ok.STATE*/ }; var RobomowButtonControllerTriggerTime = 300; // Länge eines Tastendrucks // Zonen mit Anzahl der nötigen Tastendrücke zur Auswahl, anpassen an eigene Gegebenheiten var RobomowZones = { 'L1': 0, // Hauptzone 'A1': 1, // Nebenzonen //'L2': 1, //'L3': 2, //'A2': 4, //'A3': 5, //'A4': 6 }; // Tastendrücke für einzelne Kommandos mit Wartezeit nach dem Tastendruck // ZONE_SELECT nutzen die Infos oben um die gewünschte Zone zu wählen var RobomowButtonFlows = { 'STOP': [ {command:'STOP', wait: 3000} ], 'HOME_UNLOCKED': [ {command:'STOP', wait: 3000}, {command:'HOME', wait: 1000} ], 'HOME_CHILDLOCK': [ {command:'STOP', wait: 3000}, {command:'HOME', wait: 1000}, {command:'OK', wait: 1000} ], 'MOW_NORMAL': [ {command:'RIGHT', wait: 1000}, {command:'ZONE_SELECT', wait: 1000}, {command:'OK', wait: 1000} ], 'MOW_WITH_EDGE': [ {command:'LEFT', wait: 1000}, {command:'ZONE_SELECT', wait: 1000}, {command:'OK', wait: 1000} ] }; createState("javascript." +instance + ".Robomow.InBetrieb", {'type': 'boolean', 'read': true, 'write': true, 'role': 'switch', 'def': true}); createState("javascript." +instance + ".Robomow.Command.Aktion", {'type': 'string', 'read': true, 'write': true, 'role': 'value', 'def': ""}); createState("javascript." +instance + ".Robomow.Command.Zone", {'type': 'string', 'read': true, 'write': true, 'role': 'value', 'def': ""}); function processRobomowCommand(commandname, zone, callback) { if (typeof zone === 'function') { callback = zone; zone = undefined; } if (!getState("javascript." +instance + ".Robomow.InBetrieb").val) { console.log("Got Robomow command but device is not active!"); if (callback) callback(); return; } var buttonFlow = []; if (commandname !== 'STOP') { // 3x OK to Wake up and maybe ack errors?! buttonFlow.push({command:'OK', wait: 1000}); buttonFlow.push({command:'OK', wait: 1000}); buttonFlow.push({command:'OK', wait: 1000}); } for (var i = 0;i < RobomowButtonFlows[commandname].length; i++) { var currentCommand = RobomowButtonFlows[commandname][i]; if (RobomowButtons[currentCommand.command] === true) { buttonFlow.push(currentCommand); } else if (currentCommand.command === 'ZONE_SELECT') { if (zone && RobomowZones[zone] !== undefined) { for (var j=0; j < RobomowZones[zone]; j++) { buttonFlow.push({command:'RIGHT', wait: 1000}); } } else { //ERROR } } else { //ERROR } } function processCommands(callback) { if (buttonFlow.length > 0) { var current = buttonFlow.shift(); if (RobomowButtonController[current.command]) { setState(RobomowButtonController[current.command], true, false); console.log('Press ' + current.command + ', wait=' + current.wait); setTimeout(function() { setState(RobomowButtonController[current.command], false, false); console.log(' Release ' + current.command); }, RobomowButtonControllerTriggerTime); } else { console.log('Command-State undefined for ' + current.command + ', wait=' + current.wait); } setTimeout(processCommands, (RobomowButtonControllerTriggerTime + current.wait), callback); } else { setState("javascript." +instance + ".Robomow.Command.Aktion", commandname, true); if (!zone) zone = ""; setState("javascript." +instance + ".Robomow.Command.Zone", zone, true); if (callback) callback(); } } processCommands(callback); } on({id: "javascript.0.Robomow.Command.Aktion", change: 'any', ack: false}, function(data) { var zone = getState("javascript." +instance + ".Robomow.Command.Zone").val; console.log("Trigger for command: " + data.state.val + ' for zone ' + zone); processRobomowCommand(data.state.val, zone); });` 3.) Automatisierung der Steuerung Dieses Skript übernimmt die komplette Automatisierung der Robomow-Steuerung und setzt dabei auf die anderen beiden Skripte auf. Bedeutet: Sowohl der Status als auch die Steuerung muss aktiv sein und funktionieren. Im Skript gibt man sowohl die Laufzeiten pro Tag an, also auch den Ablauf eines Mäh-Zyklus mit Angabe der Zeiten je Schritt. Den Rest regelt die Automatik :) Das Skript hat wieder zu Beginn einige Einstellungen. Es gibt einige States die als Information bzw für die eigene Verwendung geschrieben werden und am Ende die Option die Automatik zu ein- und auszuschalten. Hier das Skript: v20180101 `~~[code]~~var stateIdRobomowStatus = 'javascript.0.Robomow.Status'/*Robomow.Status*/; var stateIdRobomowPresence = 'hm-rpc.1.CUX0300004.1.STATE'/*EG-Garten Robomow Anwesenheit:1.STATE*/; var stateIdRainpause = 'javascript.0.Robomow.Regenpause'; var stateIdOutsideTemperatur = 'hm-rpc.1.CUX9002012.1.TEMPERATURE'; var minimumWorkingTemperature = 8; // erst ab 8 Grad Celsius losfahren var RobomowZoneNames = { 'L1': 'Hauptzone', // Hauptzone 'L2': 'Hauptzone 2', 'L3': 'Hauptzone 3', 'A1': 'Nebenzone', // Nebenzonen 'A2': 'Nebenzone 2', 'A3': 'Nebenzone 3', 'A4': 'Nebenzone 4' }; var mowSchedule = [ [ // 0 = Sunday ], [ // 1 = Monday { 'start': '10:30', 'end': '13:30' } ], [ // 2 = Tuesday { 'start': '10:30', 'end': '13:30' } ], [ // 3 = Wednesday { 'start': '10:30', 'end': '13:30' } ], [ //4 = Thursday { 'start': '10:30', 'end': '13:30' } ], [ // 5 = Friday { 'start': '10:30', 'end': '13:30' } ], [ // 6 = Saturday ] ]; var MowCycle = [ { action: 'MOW_WITH_EDGE', zone: 'L1', duration: 180 // Minuten }, { action: 'MOW_NORMAL', zone: 'A1', duration: 110 // Minuten } ]; var mowHomeCommand = 'HOME_CHILDLOCK'; function scheduleNextRun(scheduleString, callback) { try { var sched = schedule(scheduleString, callback); console.log('Schedule next run for ' + scheduleString + ': Date: ' + sched.nextInvocation().toString()); setState('javascript.' +instance + '.Robomow.Steuerung.NaechsterStart', sched.nextInvocation().getTime(), true); return sched; } catch (err) { console.log('Schedule next run for ' + scheduleString + ': Error: ' + err.message); } return null; } function findFutureSchedule(startDay, stopDay, startFunction) { if (startDay === 7) startDay = 0; var thatDaySchedules = mowSchedule[startDay]; console.log('Check ' + thatDaySchedules.length + ' schedules for day ' + startDay); if (thatDaySchedules.length === 0) { if (startDay === stopDay) { console.log('Iterated one whole week without new schedule found, nothing planned at all'); return null; } console.log('Nothing planned for day ' + startDay + '. Search next day'); return findFutureSchedule(startDay + 1, stopDay, startFunction); } var endArr = thatDaySchedules[0].end.split(':'); var endTime = endArr[1] + ' ' + endArr[0] + ' * * ' + startDay; var startArr = thatDaySchedules[0].start.split(':'); var startTime = startArr[1] + ' ' + startArr[0] + ' * * ' + startDay; console.log('First schedule of day ' + startDay + ': start in future, register schedule'); return scheduleNextRun(startTime, function() { startFunction(endTime); }); } function getNextSchedule(startFunction) { var currentDay = new Date().getDay(); var currentDaySchedules = mowSchedule[currentDay]; for (var i=0; i < currentDaySchedules.length; i++) { if (compareTime(currentDaySchedules[i].end, null, '>')) { console.log('Daily schedule ' + i + ': end before current timepoint, check next'); continue; } var endArr = currentDaySchedules[i].end.split(':'); var endTime = endArr[1] + ' ' + endArr[0] + ' * * ' + currentDay; if (compareTime(currentDaySchedules[i].start, currentDaySchedules[i].end, 'between')) { console.log('Daily schedule ' + i + ': current timepoint inside schedule, start directly'); startFunction(endTime); return null; } else if (compareTime(currentDaySchedules[i].start, null, '<' )) { var startArr = currentDaySchedules[i].start.split(':'); var startTime = startArr[1] + ' ' + startArr[0] + ' * * ' + currentDay; console.log('Daily schedule ' + i + ': start in future, register schedule'); return scheduleNextRun(startTime, function() { startFunction(endTime); }); } } console.log('Nothing todo today anymore, check next day'); return findFutureSchedule(currentDay + 1, currentDay, startFunction); } createState('javascript.' +instance + '.Robomow.Automatik', {'type': 'boolean', 'read': true, 'write': true, 'role': 'switch', 'def': false}); createState('javascript.' +instance + '.Robomow.PauseRestHeute', {'type': 'boolean', 'read': true, 'write': true, 'role': 'switch', 'def': false}); createState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchritt', {'type': 'number', 'read': true, 'write': true, 'role': 'value', 'def': -1}); createState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchrittDauer', {'type': 'number', 'read': true, 'write': true, 'role': 'value', 'def': 0}); createState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchrittEckeGemaeht', {'type': 'boolean', 'read': true, 'write': true, 'role': 'switch', 'def': false}); createState('javascript.' +instance + '.Robomow.Steuerung.AktuellerZyklusDauer', {'type': 'number', 'read': true, 'write': true, 'role': 'value', 'def': 0}); createState('javascript.' +instance + '.Robomow.Steuerung.LetzterZyklusDauer', {'type': 'number', 'read': true, 'write': true, 'role': 'value', 'def': 0}); createState('javascript.' +instance + '.Robomow.Steuerung.AktuelleAktion', {'type': 'string', 'read': true, 'write': true, 'role': 'value', 'def': ''}); createState('javascript.' +instance + '.Robomow.Steuerung.AktuelleZone', {'type': 'string', 'read': true, 'write': true, 'role': 'value', 'def': ''}); createState('javascript.' +instance + '.Robomow.Steuerung.AktuelleZoneName', {'type': 'string', 'read': true, 'write': true, 'role': 'value', 'def': ''}); createState('javascript.' +instance + '.Robomow.Steuerung.NaechsterStart', {'type': 'number', 'read': true, 'write': false, 'role': 'value.time', 'def': 0}); var currentMowCycleStep = getState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchritt').val; if (currentMowCycleStep === null) currentMowCycleStep = -1; var currentMowCycleStepDuration = getState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchrittDauer').val || 0; var currentMowCycleDuration = getState('javascript.' +instance + '.Robomow.Steuerung.AktuellerZyklusDauer').val || 0; var lastMowCycleDuration = getState('javascript.' +instance + '.Robomow.Steuerung.LetzterZyklusDauer').val || 0; var currentMowCycleStepEdgeDone = getState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchrittEckeGemaeht').val || false; console.log('Init Script: currentStep=' + currentMowCycleStep + ', currentStepDuration=' + currentMowCycleStepDuration + ', cycleDuration=' + currentMowCycleDuration + ', lastCycleDuration=' + lastMowCycleDuration); var currentAction = getState('javascript.' +instance + '.Robomow.Steuerung.AktuelleAktion').val || ''; var currentZone = getState('javascript.' +instance + '.Robomow.Steuerung.AktuelleZone').val || ''; var currentActionStartTime; var robomowWorkingSubscription = null; var robomowTemperatureSubscription = null; var currentRobomowEndSchedule = null; var currentRobomowStartSchedule = getNextSchedule(robomowWork); var robomowStopStepTimeout = null; on({id: stateIdRainpause, change: 'ne'} , function(data) { if (!data.state.val && robomowWorkingSubscription && getState(stateIdRobomowPresence).val) { console.log('Regenpause beendet und Arbeitszeit läuft noch, los schicken'); mowEngine(); } }); schedule('0 0 * * *', function() { if (!currentRobomowStartSchedule) { if (currentRobomowStartSchedule) clearSchedule(currentRobomowStartSchedule); currentRobomowStartSchedule = getNextSchedule(robomowWork); if (currentRobomowStartSchedule) console.log('Schedule registered for work later today'); else console.log('Nothing planned currently, check back tomorrow'); } setState('javascript.' +instance + '.Robomow.PauseRestHeute', false, true); }); on({id: 'javascript.' +instance + '.Robomow.PauseRestHeute', change: 'ne', ack: false}, function(data) { if (data.state.val && robomowWorkingSubscription) { console.log('Robomow Pause Rest heute während Arbeitszeit angefordert.'); robomowEndWork(); } setState('javascript.' +instance + '.Robomow.PauseRestHeute', data.state.val, true); }); on({id: 'javascript.' +instance + '.Robomow.Automatik', change: 'ne', ack: false} , function(data) { console.log('Neuer Robomow Automatik Status: ' + data.state.val); if (!data.state.val && robomowWorkingSubscription) { console.log('Robomow Automatik deaktiviert während Arbeitszeit'); robomowEndWork(); } setState('javascript.' +instance + '.Robomow.Automatik', data.state.val, true); }); function robomowEndWork(endOnly) { console.log('End Robomow for today, register schedule for tomorrow'); if (currentRobomowEndSchedule) clearSchedule(currentRobomowEndSchedule); currentRobomowEndSchedule = null; if (robomowWorkingSubscription) unsubscribe(robomowWorkingSubscription); robomowWorkingSubscription = null; if (robomowTemperatureSubscription) unsubscribe(robomowTemperatureSubscription); robomowTemperatureSubscription = null; if (robomowStopStepTimeout) clearTimeout(robomowStopStepTimeout); robomowStopStepTimeout=null; if (getState(stateIdRobomowStatus).val === 'Mähen' && !getState(stateIdRobomowPresence).val) { console.log('Robomow needs to come home, working time is over'); processRobomowCommand(mowHomeCommand, function(err) { console.log('Robomow needs to come home: sended'); }); } else if (getState(stateIdRobomowPresence).val) { checkMowStep(); // prepare next day } if (!endOnly) currentRobomowStartSchedule = getNextSchedule(robomowWork); } function robomowWork(endSchedule) { if (currentRobomowStartSchedule) clearSchedule(currentRobomowStartSchedule); currentRobomowStartSchedule = null; console.log('Start Robomow working time'); robomowWorkingSubscription = subscribe({id: stateIdRobomowStatus, change: 'ne'}, function(data) { if (data.oldState.val === 'Laden' && data.state.val !== 'Laden' && data.state.val !== 'Fehler' && getState(stateIdRobomowPresence).val) { console.log('Status changed: Start next Robomow Engine-Step'); mowEngine(); } else if (data.oldState.val === 'Mähen' && data.state.val === 'Fehler') { console.log('Status changed to Error, try to get him home once'); if (robomowStopStepTimeout) clearTimeout(robomowStopStepTimeout); robomowStopStepTimeout=null; processRobomowCommand(mowHomeCommand, function(err) { console.log('Robomow needs to come home: sended'); }); } }); mowEngine(); currentRobomowEndSchedule = schedule(endSchedule, robomowEndWork); } function mowEngine() { if (!getState('javascript.' +instance + '.Robomow.Automatik').val) { console.log('Automatik disabled'); return; } if (getState('javascript.' +instance + '.Robomow.PauseRestHeute').val) { console.log('Rest von heute ist Pause. Kein Einsatz'); return; } if (getState(stateIdRainpause).val) { console.log('Aktuell Regenpause. Kein Einsatz'); return; } if (parseFloat(getState(stateIdOutsideTemperatur).val) < minimumWorkingTemperature) { console.log('Zu kalt, <8 Grad. Kein Einsatz'); robomowTemperatureSubscription = on({id: stateIdOutsideTemperatur, valGe: minimumWorkingTemperature}, function(data) { unsubscribe(robomowTemperatureSubscription); console.log('Minimal-Temperatur erreicht'); if (robomowWorkingSubscription) mowEngine(); }); return; } if ((getState(stateIdRobomowStatus).val === 'Laden') || (getState(stateIdRobomowStatus).val === 'Mähen')) { console.log('Ignore Enginecall, Robomow Status: ' + getState(stateIdRobomowStatus).val); return; } if (!getState(stateIdRobomowPresence).val) { console.log('Ignore Enginecall, Robomow absent'); return; } checkMowStep(); if (currentMowCycleStep === -1) { console.log('Cycle finished, we pause till next Enginecall'); //if (currentRobomowEndSchedule) robomowEndWork(); return; // Pause till next call } currentAction = MowCycle[currentMowCycleStep].action; currentZone = MowCycle[currentMowCycleStep].zone; var currentNeededDuration = MowCycle[currentMowCycleStep].duration - currentMowCycleStepDuration; console.log('Engine: Action=' + currentAction + ', Zone=' + currentZone + ', needed-duration=' + currentNeededDuration + 'min'); if (currentAction === 'MOW_WITH_EDGE' && currentMowCycleStepEdgeDone) { currentAction = 'MOW_NORMAL'; console.log('Engine Update: Action=' + currentAction); } setState('javascript.' +instance + '.Robomow.Steuerung.AktuelleAktion', currentAction, true); setState('javascript.' +instance + '.Robomow.Steuerung.AktuelleZone', currentZone, true); setState('javascript.' +instance + '.Robomow.Steuerung.AktuelleZoneName', RobomowZoneNames[currentZone], true); startMow(currentAction, currentZone, currentNeededDuration); } function startMow(currentAction, currentZone, currentNeededDuration, secondTry) { var mowActionStarted = false; presenceEndSubscription = null; console.log('Engine: send Mow Command ' + currentAction + ' for ' + currentZone); processRobomowCommand(currentAction, currentZone, function(err) { console.log(' Mow Command sended ' + currentAction + ' for ' + currentZone); // Check that Robomow started his work var presenceStartSubscription = subscribe({id: stateIdRobomowPresence, val: false}, function(data) { console.log(' Robomow absent after command ...'); // Robomow started mowActionStarted = true; unsubscribe(presenceStartSubscription); presenceStartSubscription = null; currentActionStartTime = new Date().getTime(); // stop Robomow after maximum needed Time and let him drive home robomowStopStepTimeout = setTimeout(function() { console.log(' Return-Home timer fired'); robomowStopStepTimeout=null; processRobomowCommand(mowHomeCommand, function(err) { console.log(' Robomow needs to come home: sended'); }); }, (MowCycle[currentMowCycleStep].duration - currentMowCycleStepDuration) * 60 * 1000); console.log(' Set Return-Home timer for in ' + (MowCycle[currentMowCycleStep].duration - currentMowCycleStepDuration) + 'mins'); // handle cases when Robomow is back presenceEndSubscription = subscribe({id: stateIdRobomowPresence, val: true}, function(data) { function handleRobomowBack(data) { if (robomowStopStepTimeout) clearTimeout(robomowStopStepTimeout); robomowStopStepTimeout=null; // Work finished for now unsubscribe(presenceEndSubscription); presenceEndSubscription = null; if (getState(stateIdRobomowStatus).val !== 'Fehler') { currentMowCycleStepDuration += elapsedTime; setState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchrittDauer',currentMowCycleStepDuration, true); currentMowCycleDuration += elapsedTime; setState('javascript.' +instance + '.Robomow.Steuerung.AktuellerZyklusDauer',currentMowCycleDuration, true); if (!robomowWorkingSubscription) checkMowStep(); // If Robomow is back after his working time prepare next day } else { console.log(' Returned from Error ... we use Loading time to calculate Step time'); var loadingStart = null; var loadingSubscription = on({id: stateIdRobomowStatus, change: 'ne'}, function(data) { if (data.state.val === 'Laden' && !loadingStart) { loadingStart = new Date().getTime(); } else if (data.state.val === 'Fertig-Laden' && loadingStart) { unsubscribe(loadingSubscription); var elapsedTime = (new Date().getTime() - loadingStart) / 60000; elapsedTime = parseInt(elapsedTime.toFixed()); currentMowCycleStepDuration += elapsedTime; setState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchrittDauer',currentMowCycleStepDuration, true); currentMowCycleDuration += elapsedTime; setState('javascript.' +instance + '.Robomow.Steuerung.AktuellerZyklusDauer',currentMowCycleDuration, true); if (!robomowWorkingSubscription) checkMowStep(); // If Robomow is back after his working time prepare next day } else { console.log('INVALID: Robomow-Status ' + data.state.val); unsubscribe(loadingSubscription); } }); } console.log(' Work done for now for step ' + currentMowCycleStep + ' (' + JSON.stringify(MowCycle[currentMowCycleStep]) + '): stepDuration=' + currentMowCycleStepDuration + ', cycleDuration=' + currentMowCycleDuration); } console.log(' Robomow is back present ...'); var elapsedTime = (new Date().getTime() - currentActionStartTime) / 60000; elapsedTime = parseInt(elapsedTime.toFixed()); if (currentAction === 'MOW_WITH_EDGE' && elapsedTime < 15 && presenceEndSubscription) { setTimeout(function() { if (getState(stateIdRobomowPresence).val) { //Robomow still there after 10s console.log(' ERROR: Robomow still present after 20s?!'); handleRobomowBack(data); return; } console.log(' Was planned with EDGE and <15min, so assume Edge and wait for next present notify'); if (elapsedTime > 3) { currentMowCycleStepEdgeDone = true; setState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchrittEckeGemaeht', true, true); console.log(' EDGE Done!'); } currentAction = 'MOW_NORMAL'; setState('javascript.' +instance + '.Robomow.Steuerung.AktuelleAktion', currentAction, true); }, 10000); // 10 Seconds after start we should have a presence change return; } handleRobomowBack(data); }); }); setTimeout(function() { if (!mowActionStarted) { console.log(' Engine: ERROR Robomow not started to do work within 20s after send command'); unsubscribe(presenceStartSubscription); presenceStartSubscription = null; if (!secondTry) { startMow(currentAction, currentZone, currentNeededDuration, true); } else { sendTo('pushover.2', "send", { message: 'Robomow nicht losgefahren. Prüfen!', sound: "" }); } return; } }, 20000); // 20 Seconds after start we should have a presence change }); } function checkMowStep() { console.log('Start checkMowStep ' + currentMowCycleStep + ' (' + JSON.stringify(MowCycle[currentMowCycleStep]) + '), currentStepDuration =' + currentMowCycleStepDuration); if (currentMowCycleStep === -1) { currentMowCycleStep = 0; currentMowCycleStepDuration = 0; lastMowCycleDuration = currentMowCycleDuration; currentMowCycleDuration = 0; currentMowCycleStepEdgeDone = false; setState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchrittEckeGemaeht', false, true); setState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchritt', currentMowCycleStep, true); setState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchrittDauer', currentMowCycleStepDuration, true); setState('javascript.' +instance + '.Robomow.Steuerung.AktuellerZyklusDauer', currentMowCycleDuration, true); setState('javascript.' +instance + '.Robomow.Steuerung.LetzterZyklusDauer', lastMowCycleDuration, true); setState('javascript.' +instance + '.Robomow.Steuerung.AktuelleAktion', '', true); setState('javascript.' +instance + '.Robomow.Steuerung.AktuelleZone', '', true); setState('javascript.' +instance + '.Robomow.Steuerung.AktuelleZoneName', 'Neuer Zyklus', true); console.log('Start new Cycle, Reset everything. lastMowCycleDuration =' + lastMowCycleDuration); return; } if ((MowCycle[currentMowCycleStep].duration - currentMowCycleStepDuration) < 10) { currentMowCycleStep++; currentMowCycleStepEdgeDone = false; setState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchrittEckeGemaeht', false, true); if (! MowCycle[currentMowCycleStep]) { currentMowCycleStep = -1; // cycle done } setState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchritt', currentMowCycleStep, true); console.log('Start new Step ' + currentMowCycleStep + ' (' + JSON.stringify(MowCycle[currentMowCycleStep]) + '), lastStepDuration =' + currentMowCycleStepDuration); currentMowCycleStepDuration = 0; setState('javascript.' +instance + '.Robomow.Steuerung.AktuellerSchrittDauer', currentMowCycleStepDuration, true); return; } console.log('Still in Step ' + currentMowCycleStep + ' (' + JSON.stringify(MowCycle[currentMowCycleStep]) + '), currentStepDuration =' + currentMowCycleStepDuration); } function processRobomowCommand(command, zone, callback) { if (typeof zone === 'function') { callback = zone; zone = ''; } console.log('Robomow-Command: ' + command + ' for Zone ' + zone); setState('javascript.' +instance + '.Robomow.Command.Zone', zone, false); setState('javascript.' +instance + '.Robomow.Command.Aktion', command, false); if (!callback) return; var ackSubscribe = on({id: 'javascript.' +instance + '.Robomow.Command.Aktion', ack: true, val: command}, function(data) { unsubscribe(ackSubscribe); clearTimeout(sendTimeout); callback(null); }); var sendTimeout = setTimeout(function() { unsubscribe(ackSubscribe); clearTimeout(sendTimeout); console.log('send not returned in 60 secs'); callback('send not returned in 60 secs'); }, 60000); } onStop(function (callback) { if (robomowWorkingSubscription) { robomowEndWork(true); if (getState(stateIdRobomowStatus).val === 'Mähen' && !getState(stateIdRobomowPresence).val) { console.log('Achtung: Gemähte Zeit wird nicht aufgerechnet!!'); } } if (currentRobomowStartSchedule) clearSchedule(currentRobomowStartSchedule); callback(); }, 10000);` Wer einen Regensensor hat der kann noch folgendes neues Skript nutzen um eine Regenpause-Logik zu implementieren. v20180101 `~~[code]~~var stateIdRegensensor = 'hm-rpc.1.CUX0300001.1.STATE'/*EG-Garten Regensensor:1.STATE*/; var initRegensensorObj = getState(stateIdRegensensor); var regenAktuell = initRegensensorObj.val; var regenAktuellerStart = (regenAktuell ? initRegensensorObj.lc : 0); var regenAktuellesEnde = (regenAktuell ? 0 : (((new Date().getTime() - initRegensensorObj.lc) > 15*60*1000) ? initRegensensorObj.lc : 0)); var regenLetztesEnde = (regenAktuell ? 0 : initRegensensorObj.lc); var regenLetzteDauer = 0; var robomowFruehesterStart = 0; var stateIdRegenpause = 'javascript.' +instance + '.Robomow.Regenpause'; createState(stateIdRegenpause, {'type': 'boolean', 'read': true, 'write': true, 'role': 'switch', 'def': false}, function() { setRegenpause(regenAktuell); }); console.log('Initialize Regendaten: regenAktuell=' + regenAktuell + ', regenAktuellerStart=' + new Date(regenAktuellerStart) + ', regenAktuellesEnde=' + new Date(regenAktuellesEnde) + ', regenLetztesEnde=' + new Date(regenLetztesEnde)); function setRegenpause(val) { robomowRegenPause = val; setState(stateIdRegenpause, robomowRegenPause, true); } var regenDauerTimeout = null; var robomowRegenpauseResetTimeout = null; on({id: stateIdRegensensor, change:'ne'}, function(data) { if (regenDauerTimeout) { clearTimeout(regenDauerTimeout); regenDauerTimeout = null; } if (robomowRegenpauseResetTimeout) { clearTimeout(robomowRegenpauseResetTimeout); robomowRegenpauseResetTimeout = null; } if (data.state.val === true) { // Regen erkannt console.log('Regen erkannt: regenAktuell=' + regenAktuell + ', regenAktuellerStart=' + new Date(regenAktuellerStart) + ', regenAktuellesEnde=' + new Date(regenAktuellesEnde) + ', regenLetztesDauer=' + (regenLetzteDauer/(60*1000))); if (regenAktuellerStart !== 0 && (data.state.ts - regenAktuellesEnde) < 15*60*1000 /*&& (regenLetzteDauer === 0 || regenLetzteDauer > 120*1000)*/) { // Letztes Ende vom Regen weniger als 15 Minuten her, zusammenfassen console.log(' Letztes Ende vom Regen zurücksetzen weil nur ' + ((data.state.ts - regenAktuellesEnde)/(60*1000)) + 'min her.'); regenAktuellesEnde = 0; } else { regenAktuellerStart = data.state.ts; console.log('Regen erkannt, setze Start auf jetzt und Robomow Regenpause (bisher=' + robomowRegenPause + ')'); } regenAktuell = true; setRegenpause(true); } else { console.log('Regen Ende erkannt'); // Regen zuende regenAktuellesEnde = data.state.ts; /*if (regenAktuellesEnde - regenAktuellerStart < 120*1000) { regenAktuell = false; setRegenpause(false); regenAktuellerStart = 0; regenAktuellesEnde = 0; console.log('Regenerkennung <2Minuten, ignorieren und Robomow-Sperre aufheben'); return; }*/ regenDauerTimeout = setTimeout(function() { regenDauerTimeout = null; // Nach 15 Minuten betrachten wir Regen als beendet und setzen die Werte korrekt. regenLetzteDauer = regenAktuellesEnde - regenAktuellerStart; regenLetztesEnde = regenAktuellesEnde; regenAktuellerStart = 0; regenAktuellesEnde = 0; regenAktuell = false; var regenDauerMins = regenLetzteDauer / (60*1000); console.log(' letzte Regendauer: ' + regenDauerMins + 'min'); if (regenLetzteDauer > 4*60*60*1000) { regenLetzteDauer = 4*60*60*1000; console.log(' maximale Wartezeit von 12h erreicht, setzte auf 12h'); } var robomowFruehesterStartNeu = regenLetztesEnde + (regenLetzteDauer * 3); if (robomowFruehesterStartNeu > robomowFruehesterStart) { robomowFruehesterStart = robomowFruehesterStartNeu; } else { console.log(' Letzter Frühester Start ist später als neuer, nimm den alten Wert'); } var robomowWartezeit = robomowFruehesterStart - new Date().getTime(); if (robomowWartezeit < 0) robomowWartezeit = 0; console.log(' Frühester Start Robomow = ' + new Date(robomowFruehesterStart) + ' - wartezeit ' + (robomowWartezeit/(60*1000)) + 'min'); robomowRegenpauseResetTimeout = setTimeout(function() { robomowRegenpauseResetTimeout = null; setRegenpause(false); console.log('Robomow Regenpause vorbei'); }, robomowWartezeit); }, 15*60*1000); } }); [/code]` In Summe ist überall viel Logging noch drin,aber damit sieht man was so passiert :-) Viel Spass damit Ingo[/i][/i][/i][/i][/i][/i][/code][/i]
-
-
v20170731:
- Alles aktualisiert und alle drei Skripte Verfügbar gemacht
v20170415:
- Handling von komischen Zustandsübergängen verbessert
v20180101:
-
Allgemein Aktualisierung auf aktuellen Stand mit vielen Optimierungen und Fehlerbehebungen
-
Regenpause-Logik (neuer State und auch neues Skript, siehe Post #1!) eingefügt
-
Optimierungen in der Logik
-
Logik für Zwangspause Rest des aktuellen Tages inkl. Heimholen beim einschalten
-
Minimale Arbeitstemperatur berücksichtigt
-
stopScript Logik hinzugefügt
-
Logging, Heim-Holen wenn unterwegs und Bestätigung für Automatikänderungen eingeführt
-
Hallo Apollon,
ich nutze einen Robomow RC 306 Mäher. Ich versuche in den nächsten Tagem mal dein Script. Ich würde gerne die Programmierung des Mähers auch in Vis einbauen, allerdings habe ich noch keine Idee dazu. Ich melde mich bezüglich deines Scripts bestimmt die Tage nochmal wenn ich es im Einsatz habe.
Danke schonmal dafür.
Gruß Sven
-
Dann bin ich gespannt ob die Werte grob auch passen.
Ich würde gerne die Programmierung des Mähers auch in Vis einbauen, allerdings habe ich noch keine Idee dazu. `
Da gibt es nur eine Option aktuell (weil noch keiner das Bluetooth-Protokoll rausgefunden hat): http://www.roboter-forum.com/showthread … -Homematic
Kurz: man verbaue HM-Schaltaktoren und zapft das Kabel an wo die Tastendrücke an das Mainboard gemeldet werden und so kann man die Tasten fernbedienen ... Steht bei mir noch auf der Umbauliste
-
Ich bin auch am überlegen meinen RC306 zu integrieren.
Morgen kommt da erst mal ein neues Update drauf, dann muss ich mal schauen ob ich den
- HM-LC-Sw4-Ba-PCB mit einer 9V Batterie
oder
- ein Wemos mit ESPEasy wie hier beschrieben. https://www.loxforum.com/forum/faqs-tut … -einbinden
Würde den dann per MQTT einbinden.
Hat einer sowas bereits umgesetzt und kann ein wenig Erfahrungen hier posten?
Gruß
-
Ich habe es jetzt mit nem HM-8-fach Modul, 5 Relais und nem 26V->5V Spannungswandler gelöst und komme so um die Batterie rum …
-
Ich habe es jetzt mit nem HM-8-fach Modul, 5 Relais und nem 26V->5V Spannungswandler gelöst und komme so um die Batterie rum … `
Hi, ist auch ein Thema bei mir.
-
Welche Relais benutzt du?
-
Sollte man nicht lieber 5 Mofets nehmen? http://www.roboter-forum.com/showthread … post200132
-
Ich bin mir nicht sicher für welche Lösung ich mich entscheiden soll: Vor- und Nachteile von Homematic vs. Wifi
-
Schick mal ein Foto wie du das Ding im Robomow untergebracht hast.
LG,
a200.
-
-
Hi,
bin ehrlich: Ich lasse mir das gerade bauen von dem der https://www.der-technikmarkt.de/ macht. Ich kann zwar lösen, aber so alles zusammen macht so für mich mehr sinn als "Rundum-sorglospaket". Aber ja Mofets gehen auch. Ich will irgendwas haben als galvanische Trennung - ich finde es gefährlich wie einige die Open-CVollector-Ausgänge der HM-Module direkt auf die Robomow-kabel legen …
Da ich recht viel HM im Einsatz habe ist das für mich eher naheliegend.
Klar Wifi und Arduino und so geht auch, aber aus meiner Erfahrung kostet das gerade mehr Zeit bis es stabil läuft als ich erübrigen kann (die Zeit stecke ich lieber in die eigene Fingerabdruck-Lösung mit Steuerung ) Es ist immer so eine Thematik ... Standard oder selbstgebastelt. Bei selbstgebastelt versuche ich immer irgend wie dann doch eine gleiche Basis zu haben, sonst verzettel ich mich und wenn mal was ist brauche ich viel länger das zu fixen weil alles anders tickt.
Verbauen werde ich es wie im Thread bei früheren Lösungen gezeigt in dem kleinen "Kofferraum" unter der Hauptabdeckung.. Also am Motherboard mit einem selbstgebastelten Y-Kabel die 8 Kabel abgreifen und mit einem Kabel dann da hin führen. Da hast Du ca. 130x80 und 50 hoch Platz für ein kleines Gehäuse.
Wenn es mal läuft versuche ich mal ein Script zu bauen mit dem man das dann steuern kann. Am Ende sind die "Datenpunkte" für die einzelnen tasten ja Umsetzungsunabhängig, wenn man davon ausgeht das das setzen eines solchen immer einen 1s-"Impuls" auslöst sollte dann ein Steuerskript generisch funktionieren.
Ingo
-
HM wäre wir auch lieber, ich habe zwar ne paar Wemos hier am werkeln, für den Robomow wäre mir das zu unsicher.
Was hast du da genau bestellt bei denen? Wenn das ein rundum sorglospaket (DC Wandler, Y- Stecker, HM ist denke ich mal mit einer Relaisplatine) ist, dann würde ich das auch gerne ordern. Wenn dann alles noch in einer Box wäre, ist das perfekt.
Falls die nicht komplett alles zusammenbauen, Wäre Teile müsste ich da genau haben? Allein der Stecker ist für nicht schon ein Rätsel.
Gruß und Danke
-
Das Sorglospaket würde mich auch interessieren, dann wären wir schon 3.
Was würds denn kosten?
-
Ich bin gerade in Kontakt mit denen. Morgen sollte der Prototyp fertig sein.
Melde mich dann noch mal.
-
Jupp,
wenn alles glatt geht geht meine Version (=Prototyp) am Mittwoche zu mir raus und dann muss ich "nur" noch Zeit finden das Y-Kabel zu lösen und es final einzubauen …
Mit Gehäuse und Versand 99,99 EUR ... ist zumindestens mal das was ich bezahlt hab. Ist ne Hausnummer, aber mir die Teile und Zeit wert.
-
@ple:Ich bin gerade in Kontakt mit denen. Morgen sollte der Prototyp fertig sein.
Melde mich dann noch mal. `
Ich wäre auch interessiert. Allerdings bin ich mir nicht sicher ob die Relais vom vielen Ruckeln nicht kaputt gehen.Ansonsten hier meine Zusammenstellung:
5 x Leistungs-MOSFET N-Ch TO-220AB 100V 9,7 A https://www.reichelt.de/Wandler-groesse … KI515W36HC
2 x Platinensteckverbinder gerade, weiss, 8-polig https://www.reichelt.de/Platinen-Steckv … 25%2F8G+WS
1 x Streifenrasterplatine, Hartpapier, 100x100mm https://www.reichelt.de/Streifenraster/ … r=H25SR100
1 x DC/DC Konverter OKI 78SR-Serie 8W, 5V DC, SIP, Single https://www.reichelt.de/Wandler-groesse … KI515W36HC
1 x HM-MOD-Re-8 8-Kanal-Empfangsmodul https://www.elv.de/homematic-8-kanal-empfangsmodul.html
Damit wäre ich bei 30,64 € + Versand
Ob der Spannungswandler so i.O. ist, bin ich mir auch nicht sicher. Kann das sich das einer von den Spezialisten anschauen?
LG,
a200
-
Wenn wir bereits zu dritt sind, sollten wir uns überlegen, ob wir die Entwicklungskosten teilen.
Somit wäre der Gesamtpreis geringer für jeden.
Wenn ich dann noch was drauflege ist mir gesparte Zeit das wert.
-
Damit wäre ich bei 30,64 € + Versand `
Nimm lieber 6 Mosfets, dann hast Du alle Tasten unterstützt. Ich hab es mir als Anschlussklemmen machen lassen weil ich bei dem vom Mainboard kommenden kabel nicht nicht nochmal was anlösen wollte. Da macht der Steckverbinder mit 20cm Kabel daher wenig sinn in meinen Augen.
Also dann 40-45 EUR für die Teile. Dazu kommt noch etwas was als Gehäuse herhält. Ich bin bei sowas dann bereit 50 EUR durchaus für den "fachmännischen" Zusammenbau zu bezahlen
-
Damit wäre ich bei 30,64 € + Versand `
Nimm lieber 6 Mosfets, dann hast Du alle Tasten unterstützt. Ich hab es mir als Anschlussklemmen machen lassen weil ich bei dem vom Mainboard kommenden kabel nicht nicht nochmal was anlösen wollte. Da macht der Steckverbinder mit 20cm Kabel daher wenig sinn in meinen Augen.
Also dann 40-45 EUR für die Teile. Dazu kommt noch etwas was als Gehäuse herhält. Ich bin bei sowas dann bereit 50 EUR durchaus für den "fachmännischen" Zusammenbau zu bezahlen `
Tja, es sind 8 Leitungen:
X Braun = Masse
1 Rot = Stop
? Orange = ???
2 Gelb = Mähen mit Kante
3 Grün = Mähen ohne Kante
4 Blau = Home
5 Lila = Ok
X Grau = 26V+
Aber was macht die sechste Teste (Orange)?
-
Ich tippe auf "Settings" weil das die Taste ist die Fehlt, oder ?!
Müsste man mal testen
-
Ansonsten hier mal die Idee eines kleinen Steuerskripts für ioBroker :-))
`var RobomowButtons = { // Definition der Buttons 'STOP': true, 'HOME': true, 'RIGTH': true, 'LEFT': true, 'SETTINGS': true, 'OK': true }; var RobomowButtonController = { // Definition der ioBroker-States zum Triggern der einzelnen Tasten 'STOP': 'hm-rpc.0.....', 'HOME': 'hm-rpc.0.....', 'RIGTH': 'hm-rpc.0.....', 'LEFT': 'hm-rpc.0.....', 'SETTINGS': 'hm-rpc.0.....', 'OK': 'hm-rpc.0.....' }; var RobomowButtonControllerTriggerTime = 1000; // Länge eines Tastendrucks = 1 Sekunde var RobomowZones = { // Zonen mit Anzahl der nötigen Tastendrücke zur Auswahl 'L1': 0, // Hauptzone 'L2': 1, 'L3': 2, 'A1': 3, // Nebenzonen 'A2': 4, 'A3': 5, 'A4': 6 }; var RobomowButtonFlows = { 'STOP': [ {command:'STOP', wait: 3000} ], 'HOME_UNLOCKED': [ {command:'STOP', wait: 3000}, {command:'HOME', wait: 1000} ], 'HOME_CHILDLOCK': [ {command:'STOP', wait: 3000}, {command:'HOME', wait: 1000}, {command:'OK', wait: 1000} ], 'MOW_NORMAL': [ {command:'LEFT', wait: 1000}, {command:'ZONE_SELECT', wait: 1000}, {command:'OK', wait: 1000} ], 'MOW_WITH_EDGE': [ {command:'RIGHT', wait: 1000}, {command:'ZONE_SELECT', wait: 1000}, {command:'OK', wait: 1000} ] }; var lastRobomowCommand = null; var lastRobomowZone = null; function processRobomowCommand(commandname, zone, callback) { if (typeof zone === 'function') { callback = zone; zone = undefined; } var buttonFlow = []; if (commandname !== 'STOP') { // 2x STOP to Wake up ?! buttonFlow.push({command:'STOP', wait: 1000}); buttonFlow.push({command:'STOP', wait: 1000}); } for (var i = 0;i < RobomowButtonFlows[commandname].length; i++) { var currentCommand = RobomowButtonFlows[commandname][i]; if (RobomowButtons[currentCommand.command] === true) { buttonFlow.push(currentCommand); } else if (currentCommand.command === 'ZONE_SELECT') { if (zone && RobomowZones[zone] !== undefined) { for (var j=0; j < RobomowZones[zone]; j++) { buttonFlow.push({command:'RIGHT', wait: 1000}); } } else { //ERROR } } else { //ERROR } } function processCommands(callback) { if (buttonFlow.length > 0) { var current = buttonFlow.shift(); //setState(RobomowButtonController[current.command], true, false); console.log('Press ' + current.command + ', wait=' + current.wait); setTimeout(processCommands, (RobomowButtonControllerTriggerTime + current.wait), callback); } else { lastRobomowCommand = commandname; if (zone) lastRobomowZone = zone; if (callback) callback(); } } processCommands(callback); } processRobomowCommand('MOW_NORMAL', 'A1');` Das was man am Ende aufruft ist die Funktion "processRobomowCommand" mit einem Parameter für das Kommando, pot ein zweiter Parameter für die Zone. Dann werden Kommandos gesendet - bedeutet die oben angegebenen States in den definierte Abständen auf true gesetzt. Trocken läuft es .. rest sehen wir mal noch :-)[/i]
-
Nicht schlecht, besten Dank.
Ich habe gerade bei mir in der Rummelkiste noch ein 8 fach Relaisboard gefunden.
https://www.amazon.de/8-Kanal-Optokoppl … lais+board
Ich werde das erst mal einsetzen mit einem DC Wandler L7805CV. Mal schauen ob das gut läuft und auch unterzubringen ist.
Dürfte normal auch gehen.
gibt es sonst noch Infos zu der anderen bestellten Platine?
Gruß
-
Vielleicht ist das hier was?
https://www.ebay-kleinanzeigen.de/s-anz … -168-20910
https://www.ebay-kleinanzeigen.de/s-anz … -168-20910
Hab mir so eine Teil gekauft. Jetzt nur noch ein Spannungswandler und die Stecker!
Melde mich nach dem Urlaub.
a2200.