Photo-2015-05-11-21-20-18_4006

Da wir nun  in  der Firma den PRTG Network Monitor einsetzen und auch 
die Server Raumtemperatur und Luftfeuchtigkeit damit überwachen
und festhalten wollen, habe ich mich mal hingesetzt und einen
kleinen Arduino PRTG Raumsensor gebaut.

Er wird über Netzwerk angesprochen und gibt dann ein JSON-Objekt
wieder der dann im PRTG mit einen HTTP XML/REST Sensor
verarbeitet werden kann.

Die Stückliste:

Code:

#include <EEPROM.h>
#include <DHT.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <Ethernet.h>
#include "EEPROMAnything.h"

boolean gflag = false;
String parm;
const byte OW_MessurePin = 7;

IPAddress defaultIP(192, 168, 0, 86);
byte mac[] = { 0XDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

struct config_t
{
	byte ip0;
	byte ip1;
	byte ip2;
	byte ip3;
	boolean isConfig;
}
Conf;

EthernetServer server(80);

void setup()
{
	EEPROM_readAnything(0, Conf);
	IPAddress ip(Conf.ip0, Conf.ip1, Conf.ip2, Conf.ip3);
	Serial.println(Conf.isConfig);
	if (!Conf.isConfig)
	{
		Ethernet.begin(mac, defaultIP);
	}
	else
	{
		Ethernet.begin(mac, ip);
	}

	Serial.begin(9600);
	server.begin();
	Serial.print(F("Arduino PRTG Raumsensor gestartet (IP:"));
	Serial.print(Ethernet.localIP());
	Serial.println(F(")"));
}


void loop()
{
	EthernetClient client = server.available();
	if (Serial.available() > 0)
	{
		String inputLine = Serial.readStringUntil('\n');
		SerialConfig(inputLine);
	}

	if (client)
	{
		boolean currentLineIsBlank = true;

		while (client.connected())
		{
			if (client.available())
			{
				char c = client.read();

				// serch parameter from "HTTP GET"
				if (gflag) {
					if (c != ' ') {
						parm += c;
					}
					else {
						gflag = false;
					}
				}
				if (c == '?' && parm == "") {
					gflag = true;
				}

				if (c == '\n' && currentLineIsBlank)
				{
					if (parm == "")
					{
						SendInfoPage(client);
					}
					else
					{
						parm.toLowerCase();
						String result = "";

						if (parm.startsWith("sensor"))
						{
							if (parm.startsWith("all", 7))
							{
								result = GetAllSens();
							}
							else if (parm.startsWith("hum", 7))
							{
								result = GetHumSens();
							}
							else if (parm.startsWith("temp", 7))
							{
								result = GetTempSens();
							}
							else if (parm.startsWith("volt", 7))
							{
								result = GetVoltSens();
							}
						}

						if (result != "")
						{
							SendDataJson(client, result);
						}
						else
						{
							SendInfoPage(client);
						}
					}
					parm = "";
					break;
				}

				if (c == '\n')
				{
					currentLineIsBlank = true;
				}
				else if (c != '\r')
				{
					currentLineIsBlank = false;
				}
			}
		}
		delay(1);

		client.stop();
	}
}


String GetAllSens()
{
	char buffer[7];
	String result = "[{\"temperature\":";
	result += (dtostrf(Temp(), 3, 2, buffer));
	result += ", \"humidity\":";
	result += (dtostrf(Humidity(), 3, 0, buffer));
	result += ", \"voltage\":";
	result += (dtostrf(readVcc(), 3, 2, buffer));
	result += "}]";

	return result;
}


String GetTempSens()
{
	char buffer[7];
	String result = "[{\"temperature\":";
	result += (dtostrf(Temp(), 3, 2, buffer));
	result += "}]";

	return result;
}


String GetHumSens()
{
	char buffer[4];
	String result = "[{\"humidity\":";
	result += (dtostrf(Humidity(), 3, 0, buffer));
	result += "}]";

	return result;
}

String GetVoltSens()
{
	char buffer[6];
	String result = "[{\"voltage\":";
	result += (dtostrf(readVcc(), 2, 2, buffer));
	result += "}]";

	return result;
}


float Temp()
{
	delay(20);
	OneWire oneWire(OW_MessurePin);
	DallasTemperature sensors(&oneWire);
	sensors.begin();
	sensors.setResolution(12);
	sensors.requestTemperatures();
	float iTemperatur = sensors.getTempCByIndex(0);
	while (iTemperatur == 12768 || iTemperatur == 8500)
	{
		Serial.println(F("Fehlmessung, wiederhole die Messung!"));
		iTemperatur = sensors.getTempCByIndex(0);
	}

	return iTemperatur;
}


int Humidity()
{
	DHT dht(8, DHT11);
	dht.begin();
	return dht.readHumidity();
}

float readVcc() {
	// Read 1.1V reference against AVcc
	// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
	ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
	ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
	ADMUX = _BV(MUX3) | _BV(MUX2);
#else
	ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif

	delay(2); // Wait for Vref to settle
	ADCSRA |= _BV(ADSC); // Start conversion
	while (bit_is_set(ADCSRA, ADSC)); // measuring

	uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
	uint8_t high = ADCH; // unlocks both

	float result = (high << 8) | low;

	result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
	return result / 1000; // Vcc in millivolts
}

void SendInfoPage(EthernetClient client)
{
	client.println(F("HTTP/1.1 200 OK"));
	client.println(F("Content-Type: text/html"));
	client.println();
	client.println(F("<html><head><title>Arduino PRTG Raumsensor</title></head>"));
	client.println(F("<body bgcolor='#BDBDBD'><table width='100%'>"));
	client.println(F("<tr><td colspan='2' align='center'><h1>Arduino PRTG Raumsensor</h1></td></tr>"));
	client.println(F("<tr><td align='center'><table bgcolor='#FFFFFF' border = '1'>"));
	client.print(F("<tr><td colspan='2' align='center'><b>JSON API</b></td></tr>"));
	client.print(F("<tr><td>http://"));
	client.print(Ethernet.localIP());
	client.println(F("/?sensor=all</td>"));
	client.println(F("<td>Fragt alle Sensoren ab.</td></tr>"));
	client.print(F("<tr><td>http://"));
	client.print(Ethernet.localIP());
	client.println(F("/?sensor=temp</td>"));
	client.println(F("<td>Fragt den Temperatursensor ab.</td></tr>"));
	client.print(F("<tr><td>http://"));
	client.print(Ethernet.localIP());
	client.println(F("/?sensor=hum</td>"));
	client.println(F("<td>Fragt den Luftfeuchtesensor ab.</td></tr>"));
	client.print(F("<tr><td>http://"));
	client.print(Ethernet.localIP());
	client.println(F("/?sensor=volt</td>"));
	client.println(F("<td>Fragt den Spannungsversorgungs Sensor ab.</td></tr>"));
	client.println(F("</table></td></tr>"));
	client.println(F("<tr><td align='center'><table bgcolor='#FFFFFF' border = '1'>"));
	client.println(F("<tr><td colspan='2' align='center'><b>Serial Config</b></td></tr> <br />"));
	client.print(F("<tr><td>setip="));
	client.print(Ethernet.localIP());
	client.println(F("</td><td>Setzt eine neue IP-Adresse.</td></tr></body></html>"));
}

void SendDataJson(EthernetClient client, String result)
{
	Serial.println(result);
	client.println(F("HTTP/1.1 200 OK"));
	client.println(F("Content-Type: application/json"));
	client.print(F("Content-Length: "));
	client.println(result.length());
	client.println(F("Connection: close"));
	client.println();
	client.println(result);
}


void SerialConfig(String inputLine)
{
	inputLine.toLowerCase();

	if (inputLine.startsWith("setip="))
	{
		inputLine.replace("setip=", "");
		String ArrayKey[4];
		char *tmp;
		int i = 0;
		tmp = strtok(&inputLine[0u], ".");
		while (tmp) {
			ArrayKey[i++] = tmp;
			tmp = strtok(NULL, ".");

		}

		Conf.ip0 = atoi(ArrayKey[0].c_str());
		Conf.ip1 = atoi(ArrayKey[1].c_str());
		Conf.ip2 = atoi(ArrayKey[2].c_str());
		Conf.ip3 = atoi(ArrayKey[3].c_str());

		Conf.isConfig = TRUE;

		EEPROM_writeAnything(0, Conf);
		Serial.println(F("Neue IP-Adresse gespeichert, starte neu!"));
		delay(500);
		void(*pseudoReset)(void) = 0;
		pseudoReset();
	}
}


2 Kommentare

Christoph · 7. Dezember 2016 um 23:54

Hallo, die Idee gefällt mir ganz gut! Super Arbeit – gibt es auch eine Möglichkeit einen Digitalen PIN ab zu fragen ? – eventuell für einen Rauchsensor bzw. Wassersensor ?

    Avatar-Foto

    Shojo · 7. Dezember 2016 um 23:58

    Klar alles was sich an einen Arduino betreiben lässt ;o)

Schreibe einen Kommentar

Avatar-Platzhalter

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.