Neopixel Steuerung über einen ESP8266

Moderator: seppy

Antworten
Robin––01
Beiträge: 5
Registriert: 24. Mai 2021 11:57

Neopixel Steuerung über einen ESP8266

Beitrag von Robin––01 »

Moin,
Ich habe mich die letzten Monaten mit Openhab 3 auseinander gesetzt und mein Ziel ist es einige RGB stripes über Openhab zu steuern. Es sei kurz gesagt, dass ich noch ein totaler Anfänger bin. Ich habe mir Openhab 3 daher auf mein RaspberryPi 3b+ geladen und mir soweit den Mosquitto Broker eingerichtet und auch schon ein Colorpicker in der Paper UI zum laufen bekommen. Die Informationen die mein Colorpicker dann an den Broker schickt habe ich daraufhin mit MQTT.fx überprüft. Dies sind alles RGB Werte (ich habe darauf bei der Konfiguration geachtet).
Der letzte Schritt wäre meiner Meinung nach diese RGB Werte auf meinen ESP8266 zu bekommen. Im anderen Foren habe ich bereits Beispiel Codes gesehen die waren aber meist auf eine Abstimmung für Openhab 2 gedacht. Damit habe ich ein Problem weil ich nicht der beste bin, im C-Code Programmieren.
Kennt jemand eventuell ein passende Code für meine Anwendung oder kann mir anderweitig weiterhelfen.
Falls noch Informationen fehlen gerne Rückfragen stellen.

Danke schonmal im Voraus ! :D

Mfg
Robin

Benutzeravatar
udo1toni
Beiträge: 13864
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Neopixel Steuerung über einen ESP8266

Beitrag von udo1toni »

Bei Deinem Problem geht es nicht um openHAB :) sondern um die Programmierung des ESP8266.
Es gibt verschiedene Optionen für Firmware, für die Steuerung des RGB-Stripes ist es wichtig, zu wissen, welche Art Stripe das ist, also wie der Stripe angesteuert wird.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Robin––01
Beiträge: 5
Registriert: 24. Mai 2021 11:57

Re: Neopixel Steuerung über einen ESP8266

Beitrag von Robin––01 »

Das stimmt wohl wenn ich darüber nachdenke :D. Falls mein ESP-Problem hier in dieses Forum nicht reinpasst verstehe ich das. Aber sonst bin trotzdem sehr dankbar über eventuelle Hilfe. Ich habe habe ein WS2812B LED-Streifen. Diesen habe auch schon unabhängig von Openhab ansteuern können. Das Problem liegt eher darin die MQTT Informationen nun abzugreifen und nutzbar zu machen.

Mfg
Robin

Benutzeravatar
udo1toni
Beiträge: 13864
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Neopixel Steuerung über einen ESP8266

Beitrag von udo1toni »

Aber Die Ansteuerung lief nicht über den ESP8266, oder? Grundsätzlich ist es kein Problem, den WS2812B über den ESP8266 zu steuern. Beispielsweise sollte dieses Projekt nutzbar sein: https://github.com/Dullage/ESP-LED-MQTT oder auch dieses: https://www.instructables.com/ESP8266-L ... ts-WS2812/ welches sogar explizit openHAB erwähnt. Die angegebene openHAB-Konfiguration ist für das mqtt1 Binding, das lässt sich aber auch genauso in mqtt2 definieren.

Die vermutlich einfachste Variante wäre Tasmota: https://tasmota.github.io/docs/WS2812B-and-WS2813/ welches auch den WS2812B direkt unterstützt.

Allerdings muss man noch Levelshifting vorsehen, denn der ESP8266 läuft ausschließlich mit 3.3 Volt, während der WS2812B üblicherweise mit 5 Volt läuft. Das ist aber unabhängig von der genutzten Firmware :)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Robin––01
Beiträge: 5
Registriert: 24. Mai 2021 11:57

Re: Neopixel Steuerung über einen ESP8266

Beitrag von Robin––01 »

Super danke für die Hilfe:) Ich habe ein wenig rumprobiert und es schließlich zum laufen bekommen.
Ich habe nun direkt ein weiteres Anliegen. Ich möchte nun mit dieser Esp Konfiguration ein Wake-Up-Light nutzen, doch ich komme dort erneut nicht weiter. Vielleicht kann mir ja erneut wer helfen. :D
Die Code Vorlage habe ich von https://community.openhab.org/t/wake-up-light/19019

Ich habe natürlich mein Dimmer eingesetzt:
Things:

Code: Alles auswählen

//RGB1 LED strip
Thing mqtt:topic:swRGB1 "RGB1 LED strip" (mqtt:broker:MosquittoMqttBroker) {
	Channels:
		Type switch:switch "Power" [
			commandTopic="cmnd/swRGB1/POWER",
			stateTopic="stat/swRGB1/RESULT",
			transformationPattern="JSONPATH:$.POWER",
			on="ON",
			off="OFF"
		]
		Type switch : reachable "Reachable" [
			stateTopic = "tele/swRGB1/LWT",
			on="Online",
			off="Offline"
		]
		Type dimmer:dimmer "Dimmer" [
			stateTopic="stat/swRGB1/RESULT",
			commandTopic="cmnd/swRGB1/DIMMER",
			transformationPattern="REGEX:(.*Dimmer.*)∩JSONPATH:$.Dimmer"
		]
		Type colorHSB:color "Colour" [
			stateTopic="stat/swRGB1/RESULT",
			commandTopic="cmnd/swRGB1/HSBColor",
			transformationPattern="REGEX:(.*HSBColor.*)∩JSONPATH:$.HSBColor"
		]
}
Meine Items:

Code: Alles auswählen

//ESP_1_Wohnzimmer_Holzregal
Switch sRGB1 "RGB1 LED Strip" (gLights, gIndoorLights, gUpstairsLights) {channel="mqtt:topic:swRGB1:switch"}
Switch sRGB1Reachable "RGB1 LED Strip" (gReachable) { channel="mqtt:topic:swRGB1:reachable" }
Dimmer dRGB1 "RGB1 LED Strip" {channel="mqtt:topic:swRGB1:dimmer"}
Color cRGB1 "RGB1 LED Strip" {channel="mqtt:topic:swRGB1:color"}
Außerdem bekomme ich in den Rules eine Fehlermeldung bei den imports[1,2] und ich weiß nicht wie ich diese beseitige:
Rules:

Code: Alles auswählen

import org.eclipse.smarthome.core.library.types.DecimalType
import org.eclipse.smarthome.model.script.actions.Timer

var boolean mAlaramTriggered = false 
var int mCurrentDimLevel = 0
val String LOG = "WakeUp"
var Timer mWakeUpTimer = null
var Timer mDimmerTimer = null
var int mDimStep
var int mTimeStep
val int DEFAULT_DIM_STEP = 2
val int DEFAULT_TIME_STEP = 1

rule "WakeUpAlarmSwitchOn"
when
    Item WakeUpAlarmSwitch changed to ON
then
    if (WakeUpMinute.state == NULL || WakeUpHour.state == NULL) {
        logInfo(LOG, "WakeUpAlarmMinute or WakeUpAlarmHour not set, alarm not processed")
    } else {
      var int nowHour = now.getHour
      var int wakeUpHour = (WakeUpHour.state as DecimalType).intValue

      var int hours = 0
      val int hourDiff = wakeUpHour - nowHour 
      if (hourDiff >= 0) {
          hours = hourDiff
      } else {
          hours = 24 + wakeUpHour - nowHour
      }
      var int minutes = 0
      val int nowMinute = now.getMinute
      val int wakeUpMinute =  (WakeUpMinute.state as DecimalType).intValue
      var int minuteDiff = wakeUpMinute - nowMinute
      if (minuteDiff >= 0) {
          minutes = minuteDiff
      } else {
          minutes = 60 + wakeUpMinute - nowMinute
         if (hourDiff == 0) {
              hours = 24
          }
         hours--
      }
      
      var int totalMinutes = (hours*60) + minutes 
      logInfo(LOG, "Alarm will be set for: " + totalMinutes + " minutes")
      logInfo(LOG, "Alarm: "  + hours + " h " + minutes + " min")
      WakeUpAlarmTriggered.sendCommand(OFF)
      if (mWakeUpTimer !== null) {
          mWakeUpTimer.cancel
          mWakeUpTimer = null
      }
      mWakeUpTimer = createTimer(now.plusMinutes(totalMinutes), [|
                                         logInfo(LOG, "Alarm triggered! ")
                                         WakeUpAlarmTriggered.sendCommand(ON)
                                         mWakeUpTimer = null
                                         ])    
}
end

rule "WakeUpAlarmTriggeredOn"
when
    Item WakeUpAlarmTriggered changed to ON
then
   logInfo(LOG, "Alarm trigger starting to dim")
   mCurrentDimLevel = 0
   if (WakeUpDimStep.state == NULL) {
       logInfo(LOG, "Dimstep not defined using default")
       mDimStep = DEFAULT_DIM_STEP 
   } else {
       mDimStep =  (WakeUpDimStep.state as DecimalType).intValue
   }
   
   if (WakeUpTimeStep.state == NULL) {
        logInfo(LOG, "Dimstep not defined using default")
        mTimeStep = DEFAULT_TIME_STEP 
   } else {
       mTimeStep = (WakeUpTimeStep.state as DecimalType).intValue
   }
   mDimmerTimer = createTimer(now.plusMinutes(mTimeStep), [|
                               mCurrentDimLevel += mDimStep
                               logInfo(LOG, "Dimming " + mCurrentDimLevel)
                               if (mCurrentDimLevel >= 100) {
                                   logInfo(LOG,"Dimming is at its max, finished")
                                   mCurrentDimLevel = 100
                               } else {
                                   logInfo(LOG, "Reschedule dimmer " + mTimeStep + " min")
                                   mDimmerTimer.reschedule(now.plusMinutes(mTimeStep))
                               } 
                               // Enter your dimmer name here
                               dRGB1.sendCommand(mCurrentDimLevel)
                               if (mCurrentDimLevel == 100) {
                                   WakeUpAlarmSwitch.sendCommand(OFF)
                               }
                    ])
end

rule "WakeUpAlarmSwitchOff"
when
    Item WakeUpAlarmSwitch changed to OFF
then
   logInfo(LOG, "Switch off wakeup")
   if (mDimmerTimer !== null) {
       mDimmerTimer.cancel
       mDimmerTimer = null
   }
   if (mWakeUpTimer !== null) {
       mWakeUpTimer.cancel
       mWakeUpTimer = null
   }
   WakeUpAlarmTriggered.sendCommand(OFF)
end

Benutzeravatar
udo1toni
Beiträge: 13864
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Neopixel Steuerung über einen ESP8266

Beitrag von udo1toni »

Die Rule ist eine "alte" Rule aus openHAB2 Zeiten. der openHAB Core war eine Zeit lang als Eclipse SmartHome offen für Fremdimplementierungen.
Nur als kleine geschichtliche Einordnung: openHAB hat seinen Code in Eclipse zur Verfügung gestellt und die eigene Codebasis auf Eclipse umgestellt. Man erhoffte sich davon eine schnellere Entwicklung, weil Firmen so den Code selbst weiter entwickeln konnten. Leider kam aber nur sehr mäßige Resonanz und das Projekt wurde wieder zurückgebaut, weil der Aufwand, gegen Eclipse zu entwickeln schon erheblich ist.
Aus meiner Sicht hat dieser Schritt das Projekt locker um etwa ein Jahr verzögert, wobei ich natürlich nicht weiß, wie viel Code durch die Aktion "gewonnen" wurde.
Für Dich bedeutet es letztlich, dass Imports niemals das Schlüsselwort eclipse beinhalten. Im vorliegenden Code wären aber beide Imports ohnehin niemals notwendig gewesen (unter openHAB 1 musste man die Grundklassen importieren, aber da gab es noch keine Bindung an eclipse...)

Die Verwendung von Primitives ist eher ungünstig, die Rule Engine braucht unverhältnismäßig lang, um diesen Typ zu initialisieren. Besser ist es, die äquivalenten Objekte zu nutzen.

Die Prüfung auf NULL als Inhalt eines Items ist leider auch nicht hinreichend, um sicherzustellen, dass der Code nicht scheitert. Besser ist es, auf den enthaltenen Datentyp zu testen. DecimalType ist Teil von Number, die Prüfung auf Number ist hier ausreichend.
Die Berechnung von Stunde und Minute ist unverhältnismäßig aufwändig, einzig die Logausgabe verlangt diese Daten, das kann man aber leicht abwandeln. Man könnte sogar die Ausgabe in Stunden und Minuten vornehmen, aber das braucht Niemand wirklich.

Du hast zwei Rules, welche auf das selbe Item triggern und jeweils changed als Trigger nutzen. DAbei wird einmal auf ON eingegrenzt, das andere Mal auf OFF. Da in beiden Rules Teile des Codes doppelt vorkommen, ist es sinnvoller, beide Rules zu einer zusammenzufassen.

Die Dimmschritte mit minimal einer Minute Abstand auszuführen, erscheint mir etwas grob. Sinnvoller wären hier Sekunden. Natürlich muss das entsprechende Item WakeUpTimeStep in der UI angepasst werden, um Sekunden statt Minuten zu verwenden.

Minimal optimiert sehen die Rules also so aus:

Code: Alles auswählen

var Boolean mAlaramTriggered  = false 
var Integer mCurrentDimLevel  = 0
val String  LOG               = "wakeUp"
var Timer   mWakeUpTimer      = null
var Timer   mDimmerTimer      = null
var Integer mDimStep = 2
var Integer mTimeStep = 60
val Integer DEFAULT_DIM_STEP  = 2
val Integer DEFAULT_TIME_STEP = 60

rule "WakeUp Alarm Switch"
when
    Item WakeUpAlarmSwitch changed
then
    WakeUpAlarmTriggered.postUpdate(OFF)
    mDimmerTimer?.cancel
    mDimmerTimer = null
    mWakeUpTimer.cancel
    mWakeUpTimer = null
    if(newState == OFF) {
        logInfo(LOG, "Switch off wakeup")
        return;
    }
    if(!(WakeUpHour.state instanceof Number)) {
        logInfo(LOG, "WakeUpAlarmHour not set, alarm not processed")
        return;
    }
    var Integer iWakeUpTime = (WakeUpHour.state as Number).intValue * 60
    if(!(WakeUpMinute.state instanceof Number)) {
        logInfo(LOG, "WakeUpAlarmMinute not set, alarm not processed")
        return;
    }
    iWakeUpTime = iWakeUpTime + (WakeUpMinute.state as Number).intValue
    val Integer iNow = now.getHour*60 + now.getMinute
    var Integer iDiff = iWakeUpTime - iNow
    if(iDiff <= 0)
        iDiff = iDiff + 24 * 60
    logInfo(LOG, "creating Timer in {} minutes",iDiff)
    mWakeUpTimer = createTimer(now.plusMinutes(iDiff), [|
        logInfo(LOG, "Alarm triggered! ")
        WakeUpAlarmTriggered.postUpdate(ON)
    ])
end

rule "WakeUp Alarm triggered ON"
when
    Item WakeUpAlarmTriggered changed to ON
then
    logInfo(LOG, "Alarm trigger starting to dim")
    mCurrentDimLevel = 0
    mDimStep = DEFAULT_DIM_STEP 
    if(!(WakeUpDimStep.state instanceof Number))
        logInfo(LOG, "Dimstep not defined using default")
    else
        mDimStep = (WakeUpDimStep.state as Number).intValue

    mTimeStep = DEFAULT_TIME_STEP 
    if(!(WakeUpTimeStep.state instanceof Number))
        logInfo(LOG, "Dimstep not defined using default")
    else
        mTimeStep = (WakeUpTimeStep.state as Number).intValue

    mDimmerTimer = createTimer(now.plusSeconds(mTimeStep), [|
       mCurrentDimLevel = mCurrentDimLevel + mDimStep
       logInfo(LOG, "Dimming {}", mCurrentDimLevel)
       if(mCurrentDimLevel >= 100) {
           logInfo(LOG,"Dimming is at its max, finished")
           mCurrentDimLevel = 100
       } else {
           logInfo(LOG, "Reschedule dimmer in {} Seconds", mTimeStep)
           mDimmerTimer.reschedule(now.plusSeconds(mTimeStep))
       } 
       dRGB1.sendCommand(mCurrentDimLevel)
       if (mCurrentDimLevel == 100) {
           WakeUpAlarmSwitch.sendCommand(OFF)
       }
    ])
end
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Robin––01
Beiträge: 5
Registriert: 24. Mai 2021 11:57

Re: Neopixel Steuerung über einen ESP8266

Beitrag von Robin––01 »

Ich kann mich erneut nur bedanken, dass bringt mich wieder ein Schritt weiter und die Erklärung zum Thema Eclipse war darüber hinaus noch sehr interessant. Ich habe die neue Rule ausprobiert und stoße nun auf folgende Problem:

Code: Alles auswählen

iWakeUpTime = iWakeUpTime + (WakeUpMinute.state as Number).intValue
    val Integer iNow = now.getHour*60 + now.getMinute
    var Integer iDiff = iWakeUpTime - iNow
Hier gibt es ein Problem mit den Datentypen von iWakeUpTime (BigDecimal) und iNow(Integer). Ich habe versucht mit .intValue() das Problem zu lösen (Zumindest laut Compiler erfolgreich).
Und das gleiche noch mal hier:

Code: Alles auswählen

mCurrentDimLevel = mCurrentDimLevel + mDimStep
Das nächste Problem ist, dass es nichts desto trotz noch nicht läuft. Vielleicht habe ich noch irgendwo ein Anfängerfehler oder etwas veraltetes.
Deswegen hier einmal meine Sitemap die noch fehlt um den gesamten Code einmal zu sehen:

Code: Alles auswählen

sitemap alarmclock
{
 
    Frame label="Zeit" {
       Setpoint item=WakeUpHour minValue=0 maxValue=23 step=1
       Setpoint item=WakeUpMinute minValue=0 maxValue=59 step=5
       Setpoint item=WakeUpDimStep minValue=1 maxValue=100 step=5
       Setpoint item=WakeUpTimeStep minValue=1 maxValue=60 step=1
       Switch item=WakeUpAlarmSwitch
       Text item=WakeUpAlarmTriggered
        }
}
Vielen Dank im Voraus

Benutzeravatar
udo1toni
Beiträge: 13864
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Neopixel Steuerung über einen ESP8266

Beitrag von udo1toni »

Das kann eigentlich nicht sein, iWakeUpTime ist als Integer definiert und das sollte auch ausreichen, Integer ist 32 Bit groß und sollte also von -2147483648 (-2^31) bis 2147483647 (2^31 -1) reichen. Auch mCurrentDimmLevel und mDimStep sind vom Typ Integer.
Die Items sind alle vom Typ Number (NICHT Number:irgendwas)?

Siehst Du Meldungen im Log?
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Robin––01
Beiträge: 5
Registriert: 24. Mai 2021 11:57

Re: Neopixel Steuerung über einen ESP8266

Beitrag von Robin––01 »

Ja ich habe mich auch gewundert aber es wird als falsch angezeigt.
meine Items für den Wecker sehen wie folgt aus:

Code: Alles auswählen

//Wecker
Group WakeUpAlarm
Number WakeUpHour           "Wake up hour [%d]" <time> (gRestore,WakeUpAlarm)
Number WakeUpMinute         "Wake up minute [%d]" <time> (gRestore,WakeUpAlarm)
Number WakeUpDimStep        "Wake up Dim Step [%d]" <light> (gRestore,WakeUpAlarm)
Number WakeUpTimeStep       "Wake up Time Step [%d]" <time> (gRestore,WakeUpAlarm)
Switch WakeUpAlarmSwitch    "Wake up alarm [%s]" (gRestore,WakeUpAlarm)
Switch WakeUpAlarmTriggered "Wake up alarm triggered [%s]"  <alarm> (gRestore,WakeUpAlarm)
und im Log steht:
unter Problems:
{
"resource": "/o:/rules/Wecker.rules",
"owner": "_generated_diagnostic_collection_name_#0",
"code": "org.eclipse.xtext.xbase.validation.IssueCodes.incompatible_types",
"severity": 8,
"message": "Type mismatch: cannot convert from BigDecimal to Integer",
"startLineNumber": 35,
"startColumn": 25,
"endLineNumber": 35,
"endColumn": 43
}
und
{
"resource": "/o:/rules/Wecker.rules",
"owner": "_generated_diagnostic_collection_name_#0",
"code": "org.eclipse.xtext.xbase.validation.IssueCodes.incompatible_types",
"severity": 8,
"message": "Type mismatch: cannot convert from BigDecimal to Integer",
"startLineNumber": 64,
"startColumn": 27,
"endLineNumber": 64,
"endColumn": 54
}

unter Output:

Looking for git in: C:\Program Files\Git\cmd\git.exe
Looking for git in: C:\Program Files (x86)\Git\cmd\git.exe
Looking for git in: C:\Program Files\Git\cmd\git.exe
Looking for git in: C:\Users\Anwender\AppData\Local\Programs\Git\cmd\git.exe
Git installation not found.

Antworten