FHEM mit Arduino ansteuern

Begonnen von EnderPhilipp, 09 April 2017, 09:29:21

Vorheriges Thema - Nächstes Thema

EnderPhilipp

Hi Liebe FHEM-Community,

ich spiele seit ein paar Tagen mit meinem Arduino Mega und meinem Ethernetshield herum.

Mein Ziel ist es einen Sensor zubauen, welcher die Werte an FHEM schickt.

Jetzt scheitere ich schon daran irgendas zum FHEM-Server zu schicken, dabei hatte ich an Telnet gedacht.

Hier mal mein Programm:
/*
  Telnet client

This sketch connects to a a telnet server (http://www.google.com)
using an Arduino Wiznet Ethernet shield.  You'll need a telnet server
to test this with.
Processing's ChatServer example (part of the network library) works well,
running on port 10002. It can be found as part of the examples
in the Processing application, available at
http://processing.org/

Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13

created 14 Sep 2010
modified 9 Apr 2012
by Tom Igoe

*/

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 0, 291);

// Enter the IP address of the server you're connecting to:
IPAddress server(192, 168, 0, 220);

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 23 is default for telnet;
// if you're using Processing's ChatServer, use port 10002):
EthernetClient client;

void setup() {
  // start the Ethernet connection:
  Ethernet.begin(mac, ip);
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.println("connecting...");

  // if you get a connection, report back via serial:
  if (client.connect(server, 7072)) {
    Serial.println("connected");
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}

void loop() {
  // if there are incoming bytes available
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // as long as there are bytes in the serial queue,
  // read them and send them out the socket if it's open:
  while (Serial.available() > 0) {
    char inChar = Serial.read();
    if (client.connected()) {
      client.print(inChar);
    }
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    // do nothing:
    while (true);
  }
}





192.168.0.220 ist die IP vom FHEM-Server.

Das Programm ist ein Beispiel-Sketch aus der Arduino IDE.

Eigentlich müsste ich jetzt, wenn ich in der Seriellen Eingabe "set Stehlampe on" eingebe, meine Stehlampe einschalten können.

Also der Arduino gibt schonmal ein "connected" aus...

Den FHEM-Server kann ich von meinem Mac problemlos per telnet steuern.

Was mache ich falsch?  :-[

Mfg
Philipp ;D
¡¡¡ANFÄNGERALARM!!!
Raspberry Pi 3 (Hauptsystem)
Raspberry Pi B+ (Kellersonde)
Homematic,Philips Hue, LD382, nanoCul 433/868mhz, MPD, Intertechno, FIRMATA, EspEasy, SSCAM, STV, HDMI-CEC, EchoDot

Thorsten Pferdekaemper

Hi,
also eigentlich gibt es bessere Wege, einen Sensor zu bauen, der Werte an FHEM schickt, aber wenn Du das unbedingt mit Telnet machen willst...
Ich kann Dir nicht sagen, was da genau falsch läuft. Vielleicht solltest Du erst einmal den Sketch ganz stark vereinfachen, so dass er z.B. einmal alle 20 Sekunden "set Stehlampe on\n" oder sowas schickt. Dann in FHEM mal global verbose auf 5 setzen und schauen, ob was ankommt.
Gruß,
   Thorsten
FUIP

EnderPhilipp

Hi Thorsten,

welche Alternativen zu Telnet fallen dir denn ein ?

Mfg
Philipp
¡¡¡ANFÄNGERALARM!!!
Raspberry Pi 3 (Hauptsystem)
Raspberry Pi B+ (Kellersonde)
Homematic,Philips Hue, LD382, nanoCul 433/868mhz, MPD, Intertechno, FIRMATA, EspEasy, SSCAM, STV, HDMI-CEC, EchoDot

Thorsten Pferdekaemper

Zitat von: EnderPhilipp am 10 April 2017, 11:13:15welche Alternativen zu Telnet fallen dir denn ein ?
Also wenn es unbedingt Ethernet sein muss, dann z.B. mySensors (das Gateway kann selbst Sensor sein), MQTT, Polling per HTTPMOD, ECMD (Ethersex?), eigenes TCP-Protokoll per TCP-Socket,...
Gruß,
   Thorsten
FUIP

EnderPhilipp

Zitat von: Thorsten Pferdekaemper am 10 April 2017, 11:26:55
Also wenn es unbedingt Ethernet sein muss, dann z.B. mySensors (das Gateway kann selbst Sensor sein), MQTT, Polling per HTTPMOD, ECMD (Ethersex?), eigenes TCP-Protokoll per TCP-Socket,...
Gruß,
   Thorsten
Das gibt es ja doch ein paar Alternativen...

Kann ich denn das MySensors-Gateway denn auch ohne den Transreceiver verwenden?

MFG
Philipp
¡¡¡ANFÄNGERALARM!!!
Raspberry Pi 3 (Hauptsystem)
Raspberry Pi B+ (Kellersonde)
Homematic,Philips Hue, LD382, nanoCul 433/868mhz, MPD, Intertechno, FIRMATA, EspEasy, SSCAM, STV, HDMI-CEC, EchoDot

Frank_Huber

falls auf deiner Hardware ESPEasy läuft wäre das auch eine sehr einfache Variante.
kenne aber die Arduino HW zuwenig um das einzuschätzen.

Beta-User

Zitat von: EnderPhilipp am 10 April 2017, 15:09:21
Das gibt es ja doch ein paar Alternativen...

Kann ich denn das MySensors-Gateway denn auch ohne den Transreceiver verwenden?

MFG
Philipp

Sollte gehen, aber vielleicht schaust Du Dir erst mal firmata an (dem Vernehmen nach sollte man aber eher ältere Versionen davon nehmen).

Das einfache Ein- und Ausschalten eines PINs sollte damit sehr einfach gehen.

Gruß, Beta-User
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Wernieman

Must DU zum aufbauen der Verbindung wirklich die MAC mit angeben?

Und pert se finde ich es nicht schlecht mit telnet (oder nc) zu arbeiten. HTTP wäre mir dazu gleich schon wieder "zu viel Hochsprache"
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

EnderPhilipp

EspEasy und Firmata habe ich mir auch schon angeguckt.

EspEasy lässt sich auf meinem ArduinoMega leider nicht installieren.

Und mit Firmata kann ich leider nicht alle meine Sensoren verwenden.

Werde es mal mit MQTT versuchen.  :D

Mfg
Philipp
¡¡¡ANFÄNGERALARM!!!
Raspberry Pi 3 (Hauptsystem)
Raspberry Pi B+ (Kellersonde)
Homematic,Philips Hue, LD382, nanoCul 433/868mhz, MPD, Intertechno, FIRMATA, EspEasy, SSCAM, STV, HDMI-CEC, EchoDot

Thorsten Pferdekaemper

Zitat von: EnderPhilipp am 10 April 2017, 16:47:19
Werde es mal mit MQTT versuchen.  :D
...dann ziehe das am besten mal in den MQTT-Bereich um. Ich bin mir sicher, damit machst Du Rince und eisler glücklich.
Gruß,
   Thorsten
FUIP

Rince

Rince hat Urlaub  :)
Aber die MQTT Einführung Teil 3 sollte genau das Gesuchte sein  ::)
Wer zu meinen Posts eine Frage schreibt und auf eine Antwort wartet, ist hiermit herzlich eingeladen mich per PN darauf aufmerksam zu machen. (Bitte mit Link zum betreffenden Thread)

Thorsten Pferdekaemper

Zitat von: Rince am 10 April 2017, 20:25:28
Rince hat Urlaub  :)
"Urlaub" bedeutet doch die Abwesenheit von der "Arbeit". Meiner Auffassung nach ist "Arbeit" in diesem Sinne das, womit man Geld verdient. Verdienst Du mit der MQTT-FHEM-Beratung Geld? Ich glaube nicht. Das bedeutet, dass es keine Arbeit sondern im weitesten Sinne Urlaubsbeschäftigung ist.
Also hopp...
SCNR,
   Thorsten
FUIP

Rince

#12
Du hast völlig Recht.
Aber das Hemd ist näher als die Jacke oder wie auch immer der Spruch geht.

Auf meiner Urlaubs-ToDo stehen:
1 Arduino Mega, 1 W5100, 2 x BME 220, 16 Relaisboard, FHEM, MQTT Broker, LibreElec und ein Sat IP Konverter.

Das ist für meinen Bruder. Sonst hat der zu Hause kein Licht und kein Fernsehen.

Ich bin sicher, auch für diesen Thread fällt was ab, aber eben erst in einigen Tagen  8)



Davon abgesehen:
Unter dem angesprochenen Teil 3 ist ein vollständiges Codebeispiel, das funktionieren müsste. Philipp müsste es nur in die IDE copy&pasten.

Und mehr Infos rausrücken... welche Sensoren, etwas Quellcode...
Wer zu meinen Posts eine Frage schreibt und auf eine Antwort wartet, ist hiermit herzlich eingeladen mich per PN darauf aufmerksam zu machen. (Bitte mit Link zum betreffenden Thread)

EnderPhilipp

#13
Zitat von: Rince am 10 April 2017, 22:21:45
Unter dem angesprochenen Teil 3 ist ein vollständiges Codebeispiel, das funktionieren müsste. Philipp müsste es nur in die IDE copy&pasten.

Und mehr Infos rausrücken... welche Sensoren, etwas Quellcode...

Hi Rince,

ich wollte folgende Sensoren einbauen:
1. Si7021 (Temperatur & Luftfeuchtigkeit)
2. TSL2561 (Helligkeit)
3. Elechouse PN532 (NFC) [Kennt da wer eine gute Bibliothek?]
4. PIR (Bewegung)
5. HC-SR04 (Entfernung)
6. MPR121 (Berührung)
7. ein paar Analoge-Sensoren (Geräusche-Sensor, MQ135 )

Ich habe mir den Beispielcode mal für den Si7021 und meinen PIR präpariert, mehr habe ich bisher noch nicht gemacht.
Könnte sich das mal bitte anschauen und sagen, ob da Fehler drin sind?

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include "Adafruit_Si7021.h"

Adafruit_Si7021 sensor = Adafruit_Si7021();

int bewegung=23;
int bewegungsstatus=0;

byte mac[]    = {  0xDE, 0xCD, 0xBA, 0xFE, 0xEE, 0xED }; //eine MAC Adresse wählen, darf im eigenen Netz nur 1x vorkommen
IPAddress ip(192, 168, 0, 121); //eine gültige IP Adresse für das eigene Netz
IPAddress server(192, 168, 0, 38); //die Adresse wo der eigene MQTT Broker drauf läuft

void callback(char* topic, byte* payload, unsigned int length) {
  // handle message arrived
}

EthernetClient ethClient;
PubSubClient client(ethClient);

long lastReconnectAttempt = 0;

boolean reconnect() {
  if (client.connect("Arduino_1", "zuHause/Arduino_1", 0, true, "offline")) {
    // Once connected, publish an announcement...
    client.publish("zuHause/Arduino_1","online", true);
    // ... and resubscribe
    client.subscribe("inTopic");
  }
  return client.connected();
}
static char humidity[15]; //Speicherbereich reservieren um die Fechtigkeit zu speichern
static char temperature[15];
float h = 0.0;
float h_alt = 0.0;
float t = 0.0;
float t_alt = 0.0;
unsigned long previousMillisPIR = 0;
unsigned long previousMillis7021 = 0; //Zählervariable für den S , zählt Millisekunden seit dem letzten Funktionsaufruf nach oben
const long interval = 60000; //60000 Millisekunden aka 60 Sekunden, das Interval wie oft der Sensor überhaupt benutzt wird

void setup()
{
  client.setServer(server, 1883);
  client.setCallback(callback);

  Ethernet.begin(mac, ip);
  delay(1500);
  lastReconnectAttempt = 0;
 
  Serial.begin(9600);
  Serial.println("MQTT - Test!");
 
  sensor.begin();

  pinMode(bewegung, INPUT);
}

void loop()
{
  if (!client.connected()) {
    long now = millis();
    if (now - lastReconnectAttempt > 5000) {
      lastReconnectAttempt = now;
      // Attempt to reconnect
      if (reconnect()) {
        lastReconnectAttempt = 0;
      }
    }
  } else {
    // Client connected

    client.loop();
  }

unsigned long currentMillis = millis();
  //Si7021 Temperature & Humidity
  if (currentMillis - previousMillis7021 >= interval) {
    previousMillis7021 = currentMillis;
   
    h = sensor.readHumidity();    //Luftfeuchte auslesen
    t = sensor.readTemperature(); //Temperatur auslesen
  }
   
  // Prüfen ob eine gültige Zahl zurückgegeben wird. Wenn NaN (not a number) zurückgegeben wird, dann Fehler ausgeben.
  if (isnan(t) || isnan(h))
  {
    Serial.println("Si7021 konnte nicht ausgelesen werden");
    client.publish("fhem/universalsensor/Arduino","Sensorfehler",true); //true sendet die Nachricht retained, d.h. die Nachricht bleibt solange auf dem Broker, bis etwas neues kommt
  }
  else if (h == h_alt && t == t_alt)
  {
    //nix machen
  }
  else
  {
    client.publish("fhem/universalsensor/Arduino","online", true);
    dtostrf(h,6, 1, humidity);
    dtostrf(t,6, 1, temperature);
    client.publish("fhem/universalsensor/Humidity",humidity, true);
    client.publish("fhem/universalsensor/Temperature",temperature, true);
    h_alt = h; //den alten Messwert aufheben
    t_alt = t; //um nur bei Veränderung zu reagieren
    Serial.print("Luftfeuchte: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperatur: ");
    Serial.print(t);
    Serial.println(" C");
   
  }

  // PIR
  if (currentMillis - previousMillisPIR >= 2000) {
  bewegungsstatus=digitalRead(bewegung);
  if (bewegungsstatus == HIGH)
  {
    client.publish("fhem/universalsensor/Bewegugung","on", true);
  }
  else
  {
    client.publish("fhem/universalsensor/Bewegugung","off", true);
  }
  } 
}


Und was bedeutet diese Zeile? :
client.connect("Arduino_1", "zuHause/Arduino_1", 0, true, "offline")

Mfg
Philipp :D
¡¡¡ANFÄNGERALARM!!!
Raspberry Pi 3 (Hauptsystem)
Raspberry Pi B+ (Kellersonde)
Homematic,Philips Hue, LD382, nanoCul 433/868mhz, MPD, Intertechno, FIRMATA, EspEasy, SSCAM, STV, HDMI-CEC, EchoDot

Rince

Die Zeile heißt:
if (client.connect("Arduino_1", "zuHause/Arduino_1", 0, true, "offline")) {

Wird in der Einführung Teil 3 in epischer Breite beschrieben :)
Schau mal;
https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung_Teil_3#Last_Will_.26_Testament

Das ist die exakte Antwort auf deine Frage :)

Und wenn du wissen willst, warum das so komisch aussieht:
http://pubsubclient.knolleary.net/api.html#connect2
Hier bist direkt an der Quelle  8)
Wer zu meinen Posts eine Frage schreibt und auf eine Antwort wartet, ist hiermit herzlich eingeladen mich per PN darauf aufmerksam zu machen. (Bitte mit Link zum betreffenden Thread)