Schnelles Zuhause Smart Home

Master Kit-Module teilen weiterhin Lösungen mit uns :
„Als Experiment habe ich mich hier entschlossen, schnell und zu minimalen Kosten eine Art„ Smart Home “-Prototyp herzustellen. Es gab viele Hoteliers: Licht, Belüftung, Fenster, Wasser und IR-Steuerung von Elektrogeräten. Zunächst beschloss ich, mich auf ein Minimum an Aufgaben zu beschränken: Belüftung und Beleuchtung im Raum.



Das System basierte auf dem Arduino Uno mit der Fähigkeit, vier Pins unabhängig voneinander zu steuern, und mehreren drahtlosen Steuermodulen aus dem Master Kit: Einkanal- und Zweikanal- Relais MP3328 und MP3330 übernahmen die Rolle von Exekutivgeräten , und die Signale werden über einen Achtkanal- Sender an sie übertragen MP3329 bei einer Frequenz von 433 MHz.





Auf dem MP3330 ich die Kontrolle über zwei LED - Streifen über das Sofa, aufgehängt - eine gemütliche Hintergrundbeleuchtung für den Abend zu lesen, - und auf der MP3328 - die Steuerung eines Servo Maschine zum Öffnen / Schließen des Fensters.

Ich habe die Antriebsstruktur aus improvisierten Materialien gebaut, nämlich aus den Teilen des LEGO Designers.



Nun, und natürlich reichte mir eine einfache Funksteuerung nicht aus: Ich brauchte Zugriff auf das gesamte System über eine Weboberfläche und eine Echtzeit-Statusüberwachung.

Als Speicherressource habe ich Standard-MySQL verwendet, in dem ich aus Sicherheitsgründen eine Tabelle mit den Kennungen der Controller, Pins und dem Statuswert der einzelnen Steuerungen erstellt habe, wobei jeder eine gemeinsame Systemkennung zugeordnet wurde. Außerdem habe ich die Möglichkeit, einen festen Timer zum Ändern des Status einzustellen, fest verdrahtet, und dafür ist auch ein Feld vorgesehen.



Bei der Arbeit mit Web-Sockets war Arduino leicht fehlerhaft, und es war keine Zeit, die Gründe herauszufinden. Deshalb habe ich es auf einfache Weise skizziert: mit Ajax-Anfragen alle 100 ms. Dies ist natürlich katastrophal für den Verkehr (fast 30 MB pro Tag), aber für eine Wohnung mit unbegrenztem Internet reicht es zum ersten Mal aus.

Das einfachste Webinterface: 4 Tasten, eine für jeden Pin. Durch einmaliges Drücken wird der Status geändert, und durch langes Drücken wird der Timer (ich habe bisher 3 Minuten fest verdrahtet) eingestellt, um ihn zu ändern.



Infolgedessen lautet die vereinfachte Version der Logik wie folgt: Die

Webschnittstelle greift auf den Server zu und überprüft den Status der Steuerungen. Anschließend wird die Schnittstelle für die Arbeit mit dem System angezeigt: 4 Schaltflächen im entsprechenden Status:

Skripte
$.ajax({
			url: 'engine/ajax.php',
			type: 'POST',
			dataType: 'json',
			data: {action: 'getStates'},
		})
		.done(function(data) {
			for (key in data.success){
				var controller = data.success[key];
				if($('.btn#btn_' + controller.id).length === 0){
					html = '';
					html += '<div ';
					if (controller.timer_switch > 0){
						var seconds = 60  - (controller.timer_switch % 60)
						html += 'seconds="' + seconds + '"';
					}
					html += 'id="btn_' + controller.id + '" class="btn" state="' + controller.state + '"><div class="btn_timer"></div></div>';
					$('#btn_placer').append(html);
				} else {
					if (controller.state == 1){
						$('.btn#btn_' + controller.id).removeClass('btn_off').addClass('btn_on');
					} else if (controller.state == 0){
						$('.btn#btn_' + controller.id).removeClass('btn_on').addClass('btn_off');
					}
					if (controller.timer_switch > 0){
						var seconds = 60 - controller.timer_switch % 60;
						var minutes = Math.floor(controller.timer_switch / 60);
						$('.btn#btn_' + controller.id).addClass('seconds').css('background-position', (-seconds * 100) + 'px 0px').find('.btn_timer').text(minutes + 'M');
					} else {
						$('.btn#btn_' + controller.id).css('background-position', '0px 0px').removeClass('seconds').find('.btn_timer').text('');
					}
				}
			}
			setTimeout(function(){
				getStates();
			}, 1000);
		})
		.fail(function(data) {
			console.log('error');
		});



function getStates($sql){
	$result = $sql->query("SELECT * FROM `controllers` WHERE `home_id` = '1' ORDER BY `order`");
	if (isset($result->rows)){
		$result = $result->rows;
		foreach ($result as $key => $value) {
			if (strtotime($result[$key]['timer']) > -62169990000){
				// echo strtotime($result[$key]['timer']);
				$timer_switch = strtotime($result[$key]['timer']) - strtotime(date("Y-m-d H:i:s"));
				$result[$key]['timer_switch'] = $timer_switch;
				if ($timer_switch < 0){
					$sql->query("UPDATE `controllers` SET `state` = '".$result[$key]['timer_state']."', `timer` = '0000-00-00 00:00:00', `timer_state` = '' WHERE `id` = '".$result[$key]['id']."'");
				}
			}
		}
		$res['success'] = $result;
	} else {
		$res['error'] = ' ';
	}
	return $res;
}




Wenn die entsprechende Schaltfläche gedrückt wird, wird eine POST-Anforderung an die Datei ajax.php gesendet:

Javascript
$(document).on('mousedown', '.btn', function(event){
			event.preventDefault();
			var id = parseInt($(this).attr('id').replace('btn_', ''));
			click_wait = false;
			mousetimer = setTimeout(function(){
				click_wait = true;
				setTimer(id);	
			}, 2000);
		});

		$(document).on('mouseup', '.btn', function(){
			clearTimeout(mousetimer);
			if (!click_wait){
				var id = parseInt($(this).attr('id').replace('btn_', ''));
				switchController(id);
				console.log('click !!!');
				click_wait = false;
			}
		});
	function switchController(id){
		var el = $('.btn#btn_' + id);
		var state = parseInt($(el).attr('state'));
		var need_state;
		if (state == 0){
			need_state = 1;
		} else if (state == 1){
			need_state = 0;
		}
		$(el).addClass('waiting');
		$.ajax({
			url: 'engine/ajax.php',
			type: 'POST',
			dataType: 'json',
			data: {action: 'setState', id: id, state: state, need_state: need_state},
		})
		.done(function(data) {
			if (data.success == 'ok'){
				$(el).attr('state', need_state);
				$(el).removeClass('waiting').removeClass('btn_on').removeClass('btn_off');
				if(need_state == 1){
					$(el).addClass('btn_on');
				} else if(need_state == 0){
					$(el).addClass('btn_off');
				}
			}
		})
		.fail(function(data) {
			console.log('error');
		});
	}
	function setTimer(id){
		var el = $('.btn#btn_' + id);
		var state = parseInt($(el).attr('state'));
		var need_state;
		if (state == 0){
			need_state = 1;
		} else if (state == 1){
			need_state = 0;
		}
		$(el).attr('seconds', 0);
		$(el).addClass('seconds');
		$.ajax({
			url: 'engine/ajax.php',
			type: 'POST',
			dataType: 'json',
			data: {action: 'setTimer', id: id, state: state, need_state: need_state},
		})
		.done(function(data) {
		})
		.fail(function(data) {
			console.log('error');
		});
	}




In der Variablen-ID übergeben wir den Bezeichner des Controllers und im Variablenstatus den Wert seines Status. In der Datei ajax.php erhalten wir eine POST-Anfrage und fügen die neuen Daten in die Datensatzwerte der entsprechenden ID ein.

Php
function setState($sql){
	$need_state = (int)$_POST['need_state'];
	$state = (int)$_POST['state'];
	$id = (int)$_POST['id'];

	$result = $sql->query("UPDATE `controllers` SET `state` = '".$need_state."', `timer` = '0000-00-00 00:00:00' WHERE `id` = '".$id."'");
	//   Arduino
	$result = $sql->query("SELECT `state` FROM `controllers` WHERE `id` = '".$id."'");
	if ($need_state == $result->row['state']){
		$res['success'] = 'ok';
	} else {
		$res['success'] = 'err';
	}
	return $res;
}

function setTimer($sql){
	$need_state = (int)$_POST['need_state'];
	$state = (int)$_POST['state'];
	$id = (int)$_POST['id'];

	$result = $sql->query("UPDATE `controllers` SET `timer` = NOW() + INTERVAL 3 MINUTE, `timer_state` = '".$need_state."' WHERE `id` = '".$id."'");
	//   Arduino
	$result = $sql->query("SELECT `state` FROM `controllers` WHERE `id` = '".$id."'");
	if ($need_state == $result->row['state']){
		$res['success'] = 'ok';
	} else {
		$res['success'] = 'err';
	}
	return $res;
}




Arduino wiederum greift über Ethernet auf den Webserver zu, überprüft den eindeutigen Systemschlüssel, die Controller-Werte, analysiert die empfangene Zeichenfolge und wechselt die Pin-Werte.

Php
if (isset($_GET['key']) && $_GET['key'] !== ''){
		$key = $_GET['key'];
	} else {
		die;
	}
	
$key = $sql->escape($key);
	$result = $sql->query("SELECT * FROM `controllers` WHERE `home_id` = '1' AND `key` = '".$key."' ORDER BY `order`");
	foreach ($result->rows as $key => $value) {
		if ($value['id'] == '1'){
			if ($value['state'] == '1'){
				$ar .= 'Q';
			} else if ($value['state'] == '0') {
				$ar .= 'q';
			}
		}
		if ($value['id'] == '2'){
			if ($value['state'] == '1'){
				$ar .= 'W';
			} else if ($value['state'] == '0') {
				$ar .= 'w';
			}
		}
		if ($value['id'] == '3'){
			if ($value['state'] == '1'){
				$ar .= 'E';
			} else if ($value['state'] == '0') {
				$ar .= 'e';
			}
		}
	}




Danach wird eine Zeile der Form „% qUerTY“ in eine Skizze übertragen, in der sie abhängig von fest verdrahteten Regeln analysiert wird: Jeder Buchstabe entspricht seiner PIN-Nummer, und das Register ist für den Endwert verantwortlich: Großbuchstaben - 1, Kleinbuchstaben - 0.

Arduino
void readData(){
  if (led_connect){
    digitalWrite(6, HIGH);
  } else {
    digitalWrite(6, LOW);
  }
  digitalWrite(4, LOW);
  previousMillis = currentMillis;
  
  led_connect = !led_connect;
    while (client.available()){      
      switch (char c = client.read()) {
        case 'Q':
          digitalWrite(9, HIGH);
          break;
        case 'q':
          digitalWrite(9, LOW);
          break;
        case 'W':
          digitalWrite(8, HIGH);
          break;
        case 'w':
          digitalWrite(8, LOW);
          break;
        case 'E':
          digitalWrite(7, HIGH);
          myservo.write(0);
          break;
        case 'e':
          digitalWrite(7, LOW);
          myservo.write(180);
          break;
      }
    }
}



Sie können Werte von 0 bis 180 (Drehpunkte) an den für die Servomaschine zuständigen Pin und beispielsweise an den Dimmer übertragen - bis zu 255. Ich habe immer noch zwei Werte: 0 oder 1.





Es gab keine Probleme beim Anschließen der Module: beide Die Relais werden einmal mit dem Sender gekoppelt, ohne dass eine erneute Bindung erforderlich ist, und erfüllen ihre Aufgabe perfekt.





Aber mit der Kraft der Servomaschine habe ich mich ein wenig verrechnet: Ich habe 6 kg genommen - was im Allgemeinen ausreicht, um den Fensterflügel, den er unter seinem eigenen Gewicht öffnete, abzudecken und loszulassen -, aber es ist besser, etwas Stärkeres anzunehmen bei starkem Wind oder Zugluft.

Im Allgemeinen ist der Spielraum für Kreativität unbegrenzt: Sie können beispielsweise Sensoren anschließen, z. B. CO2 oder Temperatur, und das Fenster öffnen / schließen, wenn bestimmte Indikatoren erreicht sind.
Natürlich habe ich vor, das gesamte System auf Web-Sockets umzuschreiben, um Anforderungen zu vereinfachen - und die Übertragung und Analyse von Parameterwerten flexibler zu gestalten.

Skizze für Arduino

Kleines Video

Hintergrundbeleuchtung


Fenster öffnen


Dmitry Kuznetsov "

Source: https://habr.com/ru/post/de383679/


All Articles