UnboundLock

Aus HRW FabLab MediaWiki
Wechseln zu: Navigation, Suche

UnboundLock ist ein elektronisches IoT-Schloss, das an Türen aller Art installiert und mittels einer MQTT-Verbindung per Smartphone-App gesteuert werden kann. Das Schloss bietet einerseits triviale Funktionen zum Öffnen und Schließen an der Bedienschnittstelle vom Smartphone aus, bietet dem Nutzer darüber hinweg jedoch auch Möglichkeit, über sicherheitsrelevante Neuigkeiten informiert zu werden und Besuchern vor der Tür textbasierte Direktnachrichten zu hinterlassen. Der Prototyp setzt sich aus einem ESP32 mit OLED-Display, einem Schrittmotor mit zugehöriger Steuerung, einem Ultraschallabstandsmesser und einer demonstrativen App zusammen.

UnboundLock

Logo UnboundLock.png

Entwickler

Miriam Strasen, Yasar - Berke Akin, Dennis Brunne, Manuel Stodian

Projektdateien

GitHub ESP32 GitHub Android App

Verwendete Programmiersprachen

Arduino C++ Java Kotlin

Eingesetzte Software

Arduino IDE, MQTT-Explorer, Android Studio

Projektidee[Bearbeiten]

Plakat UnboundLock

Die Idee war ein COVID-19 freundliches und vielfältig einsetzbares Türenschlosssystem, das man von überall aus mittels einer App steuern kann.

Projektbeschreibung[Bearbeiten]

Während der anhaltenden, pandemischen COVID-19-Lage wird ein verantwortungsbewusstes Verhalten vorausgesetzt - und da setzt UnboundLock an. UnboundLock lässt Alltagssituationen in der Quarantäne - wie eine Paketannahme oder das Empfangen von Besuchern vor der Tür - ausschließlich kontaktlos ablaufen.
Natürlich ist die Wirksamkeit von UnboundLock während des Lock-Downs nicht dessen Alleinstellungsmerkmal. Auch danach kann es effektiv eine sicherere Paketannahmestelle im Eigenheim oder einen Empfang für nicht persönlich empfangbare Besucher darstellen.
Dank der integrierten Sensorik lässt es auch den Raum vor der Tür sicherheitstechnisch erfassen: eine Abstandssensorlogik prüft so, ob Vorgehen an der Klinke der Tür festzustellen ist, und ein Schaltlogik, ob die vermeintliche Schließung der Tür über die App auch tatsächlich zu einem Verschluss geführt hat, oder ein mögliches Hindernis die Sperrung blockiert.

Hardware[Bearbeiten]

Das Projekt bediente sich der Hardware, die in der ausgegebenen (Funduino) "Experimentierbox" bereitgestellt wurde.

Kostenaufstellung[Bearbeiten]

Komponentenliste
Bezeichnung Kosten/Stück [€] Anzahl
ESP32 0,00 1
Schrittmotor 0,00 1
Schrittmotor-Steuerung 0,00 1
Ultraschallabstandsmesser 0,00 1
5V-Netzteil 0,00 1
Relais 0,00 1
AAA Batterie 0,00 4
Batteriehalter 0,00 1
Schlossriegel 0,00 1
USB-C-Kabel 0,00 1
Verkabelung 0,00
Kosten pro Einheit: 0,00


ESP32[Bearbeiten]

Der ESP32 ist zuständig für jegliche Vermittlung zwischen dem MQTT-Netzwerk und den Komponenten vor Ort, der Sensorik und Aktorik. Wird als Beispiel von der App aus der Befehl einer Türschließung gesendet, erreicht den ESP32 die Forderung und er führt das entsprechende Protokoll aus. Leider verknappt sich die Menge an nutzbaren GPIOs, aber insbesondere ADCs, werden WiFi-Funktionen gebraucht.

Dessen beide Druckknöpfe - GPIO0 und GPIO35 - sind Teil der Benutzerschnittstellen für die Einrichtung: GPIO0 zum einen setzt das interne Dateisystem, das unter anderem die ID speichert - zurück; GPIO35 andererseits kalibriert den Ultraschallabstandsmesser.

Schrittmotor und Steuerung[Bearbeiten]

Der Schrittmotor schiebt in Korrespondenz mit den Signalen des ESP32 und seiner Steuerung den Riegel in die Verschlusslasche oder heraus.
Sollte der Motor unzureichend Leistung aufnehmen, was verhindere, dass der Schlossriegel bewegt werden kann, müsste eine physische Lösung her, die auf beiden Seiten der Tür zugänglich wäre; das ließe allerdings Potential eines Sicherheitsrisikos offen. Unser Prototyp mit der Realisierung eines Schlossriegels als Verschlusssystem unterstützt einen solchen manuellen Zugriff noch nicht.

Ultraschallabstandsmesser[Bearbeiten]

Der Ultraschallabstandsmesser ist auf die Klinke der Tür ausgerichtet und misst die vergangene Zeit des ausgesandten Signals bis zur Klinke und zurück. In einer einmaligen Kalibrierung wird die Standardzeit zur Klinke im Flash-Speicher des ESP32 gespeichert. Bei einer signifikanten Schmälerung der gebrauchten Zeit stellt der ESP32 Vorgehen an der Tür fest.

5V-Netzteil[Bearbeiten]

Das 5V-Netzteil ist der hauptsächliche Stromlieferant des UnboundLocks und versorgt den ESP32 mit 5V und 2A.

Relais[Bearbeiten]

Sollte die Hauptstomzufuhr - im Normalfall die Steckdose - überraschenderweise abgekappt werden - sei es durch einen Stomausfall, einen gezielten, menschlichen Eingriff oder durch das Versagen des 5V-Netzteils - schaltet das Relais auf die Batterieversorgung um. Der ESP32 kann so mindestens einen ziemlich geschäftigen Tag überweilen.

Batterien[Bearbeiten]

Vier Batterien sind über eine Batterienhalterung reihengeschaltet und führen in das Relais. Sie werden als Stromquellenalternative genutzt.

Schlossriegel[Bearbeiten]

Der Schlossriegel ist bloß eine austauschbare, demonstrative Umsetzung eines mechanischen Verschlusssystems. In einer nicht prototypischen Version wäre die Wahl auf eine bedeutsam installierfreundlichere und saubere Variante wie einem elektronischen Schloss mit Schlosszylinder gefallen.

Verkabelung[Bearbeiten]

Verkabelung: Relais

Der Hauptstrom ist zum einen mit dem NO-Kontakt des Relais verbunden. Das Relais verschaltet den NO-Kontakt mit dem COM-Kontakt, sollte am In-Pin ein Signal, also der Hauptstrom, anliegen. Ohne ein Signal am In-Pin bleibt COM mit NC, der Batterieversorgung, verschaltet - das tritt genau dann auf, wenn kein Hauptstrom fließt. COM leitet dann den Strom, ob er nun aus NC, den Batterien, oder NO, dem Hauptstrom, kommt, an den ESP32 weiter. Ein USB-C-Kabel ohne Daten-Lane wurde zweigeteilt: dessen USB-A-Stecker führt vom 5V-Netzteil weg in den In-Pin und ON-Kontakt, der USB-C-Stecker vom COM-Kontakt zum ESP32.

Verkabelung: Schlossriegel


Mittels einem befestigten Kabel am Schlossriegel und einem, das von der Schlossriegellasche in einen ADC-Port des ESP32 führt, kann zweifelsfrei zu jedem aktiven Moment gesagt werden, ob das Schlosssystem auch tatsächlich verschlossen oder geöffnet ist. Dazu können Schlossriegel und -lasche einen physischen Kontakt aufbauen. Abhängig, ob der Prototyp auch tandellos an der Tür angebracht wurde, kann diese Logik unwahre Aussagen produzieren.






Software[Bearbeiten]

Mithilfe der Arduino-IDE wurden die Funktionsweisen des ESP32 entwickelt. Der Programmcode liegt gänzlich in C++ vor.

Die App in Kotlin beziehungsweise Java.

ESP32[Bearbeiten]

Im diesem Abteil werden Kernschnipsel des Quellcodes vom ESP32 vorgestellt. Die Software wurde mithilfe der Arduino-IDE in C++ geschrieben.

Topics[Bearbeiten]

MQTT-Broker arbeiten mit sog. "Topics". Topics können beliebig viele Untertopics besitzen. Neben dem Broker, dem MQTT-Server, gibt es außerdem noch Subscriber und Publisher. Ein Subscriber beobachtet Änderungen einer Topic, während ein Publisher solche Änderungen erwirken kann. I.d.R. kann ein Teilnehmer sowohl Subscriber, als auch Publisher sein.
Damit das Projekt nun Daten empfangen und publizieren kann, werden zunächst relevante Topic-Namen als Char-Arrays deklariert bzw. der bereits feststehende Stamm-Topic-Name initalisiert.

char* topic_root = "ES/WS20/gruppe8/";
char topic_doorSensors[TOPIC_BUFFER_SIZE];
char topic_doorSensors_isClosed[TOPIC_BUFFER_SIZE];
char topic_doorSensors_areActionsNearHandle[TOPIC_BUFFER_SIZE];
char topic_motor[TOPIC_BUFFER_SIZE];
char topic_motor_direction[TOPIC_BUFFER_SIZE];

char topic_customText[TOPIC_BUFFER_SIZE];
char topic_newId[ID_BUFFER_SIZE];


Weil sich die endliche Topic einer UnboundLock-Einheit aus dem Stamm, einer einzigartigen ID, die zum Zeitpunkt der Deklaration noch festgestellt werden muss, und dem Thema zusammensetzt, erfolgt erst in Setup() dessen Assemblierung und Speicherung in den vorgesehenen, deklarierten Arrays.

void Setup(){
...  
 // topic_root + unitId + x = topic_x
  snprintf(topic_doorSensors, TOPIC_BUFFER_SIZE, "%s%s%s", topic_root, unitId, "/DoorSensors/#");
  snprintf(topic_doorSensors_isClosed, TOPIC_BUFFER_SIZE, "%s%s%s", topic_root, unitId, "/DoorSensors/isClosed");
  snprintf(topic_doorSensors_areActionsNearHandle, TOPIC_BUFFER_SIZE, "%s%s%s", topic_root, unitId, "/DoorSensors/actionsNearDoorHandle");
  snprintf(topic_motor, TOPIC_BUFFER_SIZE, "%s%s%s", topic_root, unitId, "/Motor/#");
  snprintf(topic_motor_direction, TOPIC_BUFFER_SIZE, "%s%s%s", topic_root, unitId, "/Motor/direction");
  
  snprintf(topic_customText, TOPIC_BUFFER_SIZE, "%s%s%s", topic_root, unitId, "/CustomUserText");
  snprintf(topic_newId, ID_BUFFER_SIZE, "%s%s%s", topic_root, unitId, "/newId");
...
}


reconnect(), was zunächst inital und auf Verbindungsprüfung auch iterativ in loop() aufgerufen wird, subscribed daraufhin mithilfe der Funktion subscribeToTopics() die Topics:
• /.../Motor/#
• /.../CustomUserText
• /.../newId

Der ESP32 erhält also im Callback vom Benutzer ausgehende Updates zum Motor - ob dieser z.B. eine Schließung oder Öffnung ausführen soll -, zu einem Wunschtext, der bis zu 30 Sekunden auf dem OLED-Display angezeigt wird, wenn er nicht bereits zuvor wiedermals modifiziert wurde, und einer benutzerdefinierten ID, die im Flash-Speicher für künftige Instanzen hinterlegt wird.

void subscribeToTopics() {
  auto subscribeToTopic = [](char* topic) {
    if(client.subscribe(topic)) {
    Serial.print("Successfully subscribed to "); Serial.println(topic);
    } else {
      Serial.print("Could not subscribe to "); Serial.println(topic);
    }
  };
  subscribeToTopic(topic_customText);
  subscribeToTopic(topic_motor_direction);
  subscribeToTopic(topic_newId);
}


Publikationen erscheinen dann, wenn innherhalb des Loops ausgewertete Sensorwerte, Ereignisse, als Anormal befunden werden.

Callback[Bearbeiten]

Die callback(char* topic, byte* payload, unsigned int length)-Funktion wird aufgerufen, bemerkt der ESP32, dass eine subscribete Topic aktualisiert wurde. Als Beispiel wird in dieser Sektion die Drehrichtung des Motors vorgeführt.
Der übergebene Parameter topic enthält den vollen Namen der jeweilig aktualisierten Topic als Char-Array und wird in der Funktionsbeschreibung in Kopplung mit strcmp(...) gebraucht, eine durch die Topic einlaufende Message dem korrespondieren Befehl zuzuordnen. Gerade die in der Sektion Topics zusammengesetzten Namen finden hier einen Einsatz.

  if(strcmp(topic_motor_direction, topic) == 0) {
    ...
  }

Der payload-Parameter enthält die eigentliche Nachricht, die der jüngst aktualisierten Topic entnommen werden konnte; length lediglich die Anzahl der Zeichen dieser Nachricht, was ein Iterieren darüber vereinfachen kann. Nun wird dieser Nachricht einen Sinn beigeordnet: da knappe Nachrichten bedeutsam schneller und performanter bearbeitet werden können, beließen wir es möglichst bei einem Zeichen, das die zugehörige Befehlsfolge zum Ausführen bewegt. Das erste Zeichen ist somit meistens der Informationsträger; ist es in Hinsicht auf die Bedingungskette ungültig, wird momentan nur zu Debug-Zwecken in der Konsole eine entsprechende Nachricht abgelegt.

  if(strcmp(topic_motor_direction, topic) == 0) {
    if(payload[0] == '1') {
      digitalWrite(MOTOR_LEFT_PIN, LOW);
      digitalWrite(MOTOR_RIGHT_PIN, HIGH);
    } else if(payload[0] == '0') {
      digitalWrite(MOTOR_RIGHT_PIN, LOW);
      digitalWrite(MOTOR_LEFT_PIN, HIGH);
    } else {
      Serial.print("Latest received message ["); Serial.print(topic); Serial.println("]: not a valid message.");
    }
  }

Publishing[Bearbeiten]

Den Nutzer kümmert meist wenig der Überlauf an Daten, die die Sensoren zu Hunderten die Sekunde hinterlassen, deshalb - und das schont nicht nur den WLAN-Traffic, sondern wahrt insbesondere die Komplexität im ESP32 - werden nur Signaturen, also Auswertungen, publiziert, die auf eine erhebliche Werteveränderung und damit auf vermeintlich menschliche Bewegungen verweisen.
Am Beispiel der Türklinken-Überwachung könnte eine Auswertung beinhalten, dass Vorgehen an dieser detektiert wurde - das tritt auf, wenn jemand die sonst recht konstant bleibende Entfernung von Tür zu der Klinke verkleinert, die Hand darauf setzt. Es wird also die aktuelle Zeit zur Klinke gemessen...

bool areActionsNearHandleLoop() {
  ...  
  unsigned int timeToDoorHandleLocal = 0;
  digitalWrite(ULTRASONIC_TRIGGER_PIN, LOW); 
  delay(5); 
  digitalWrite(ULTRASONIC_TRIGGER_PIN, HIGH); 
  delay(10);
  digitalWrite(ULTRASONIC_TRIGGER_PIN, LOW);
  timeToDoorHandleLocal = pulseIn(ULTRASONIC_ECHO_PIN, HIGH)/2;
  ...
}

... und in Toleranz eines Puffers die im Flash gespeicherte Standardzeit bis zur Klinke mit der gerade gemessenen verglichen. Ist deren Delta größer als der Puffer, wird Vorgehen gepublisht, andernfalls keines.

bool areActionsNearHandleLoop() {
  bool areActionsNearHandleLocal;
  ...
  areActionsNearHandleLocal = ((timeToDoorHandle - timeToDoorHandleLocal) > timeToDoorHandlePuffer) && timeToDoorHandleLocal != 0;
  if(areActionsNearHandleLocal != areActionsNearHandle) {
    areActionsNearHandle = areActionsNearHandleLocal;
    Serial.print("ActionsNearDoorHandle updated: "); Serial.println(areActionsNearHandle);
    client.publish(topic_doorSensors_areActionsNearHandle, (areActionsNearHandleLocal ? "1" : "0"));
  }
  ...
}

Im Flash-Speicher[Bearbeiten]

Mithilfe der Bibliothek Preferences.h wird ein Dateisystem im Flash-Speicher des ESP32 in HashMap-Manier angelegt, wenn es nicht schon existiert. Anschließend werden die Werte im Flash-Speicher in den dazugehörigen Variablen des flüchtigen gespeichert, bzw., wenn noch keine im Speicher existieren, auf die Standardwerte gesetzt und in den Variablen gespeichert:

Preferences preferences;
...
void setup() {
  preferences.begin("my-vars", false); // false means read- AND writeable

  //preferences.putString("value","0"); // HARD-CODE RESET ID
  snprintf(unitId, 32, "%s", preferences.getString("id", "0"));
  timeToDoorHandle = preferences.getUInt("standardDelay", 100);
  ...
} 

Die Bilbiothek Button2.h erlaubt, die Druckknöpfe des ESP32 zu programmieren. Damit wird beispielsweise die Kalibrierung des Ultraschallabstandsmessers user-zugänglich. Die gemessene Zeit zur Klinke unmittelbar nach Drücken von GPIO35 wird unter dem Key "standardDelay" für künftige Instanzen abgespeichert:

void on_right_button_tap(Button2& btn) {
  Serial.println("RIGHT BUTTON BEEN PRESSED");
  ... // measuring timeToDoorHandle (ttdh)
  Serial.print("TimeToDoorHandle updated: "); Serial.println(ttdh);
  preferences.putUInt("standardDelay", (ttdh));
  preferences.end();
  ESP.restart();
}

Sleep-Modus[Bearbeiten]

Der ESP32 bietet keine Sleep-Modi, die für unser Projekt konform wären. Selbst die mildeste Stufe deaktiviert WLAN-Funktionen, die für ein "ungebundenes" Schloss nicht entbehrlich sind. Stattdessen wurden über Umwege andere Lösungen zum Stromsparen implementiert - so schaltet sich das Display bzw. Display-Backlight automatisch aus, wenn es gerade nicht gebraucht wird. Es sollte eine stetige Stromzufuhr gewährleistet sein, für einen Notfall wurde durch die alternative Stromversorgung über Batterien allerdings für etwa einen Tag ohne Hauptstrom gesorgt.

App[Bearbeiten]

App Hauptbildschirm mit eingehender Nachricht

Die Android App (Ab Android 8.0; Kotlin) dient als externes Steuerelement des Schlosses.

Features[Bearbeiten]

Eingehende Meldungen des Schlosses:
Alle eingehenden Meldungen werden je nach Status der App als Notification (App im Hintergrund) oder Nachricht in der App (App im Vordergrund) angezeigt.

App Notification
  • Änderung des Status des Schloss (Geöffnet/Geschlossen/Unerwartete Fehler)
  • Meldung, falls das Schloss als "Geschlossen" gilt, aber nicht geschlossen werden konnte
  • Bewegungen am Schloss

Ausgehende Meldungen an das Schloss:

  • Änderung des Status des Schloss (Geöffnet -> Geschlossen, Geschlossen -> Geöffnet)
  • Anzeige eines Textes am Schloss

Startup[Bearbeiten]

App Login Bildschirm

Im Login Bildschirm hat der Nutzer die Möglichkeit sich mittels der IP:Port, dem Nutzernamen und dem Passwort beim MQTT Server anzumelden. Ferner wird die ID des Schlosses benötigt. Zudem ist es möglich, die Nutzerdaten für den nächsten Start zu speichern ("Remember me") und die App sich mittels dieser automatisch anmelden zu lassen ("Auto login"). Dabei wird der Nutzername und das Passwort mit AES verschlüsselt auf dem Smartphone gespeichert.

Code[Bearbeiten]

Server Connection[Bearbeiten]

Die genutzte Bibliothek ist Eclipse Paho für die Verbindung zum Server.

Festlegen der Optionen (Verbindungsdaten) für den Mqtt Server

val options = MqttConnectOptions()
options.userName = username // Nutzername für den MQTT Broker
options.password = password.toCharArray() // Passwort als Char Array
options.isAutomaticReconnect = true
options.connectionTimeout = 10 // in Sekunden

Die Verbindung zum Mqtt Server mit der ServerUrl (tcp://ip:port) und den Optionen

val mqttClient = MqttClient(serverUrl, MqttClient.generateClientId(), MemoryPersistence())
mqttClient.connect(options)
while (!mqttClient.isConnected) {
   // connecting
}
// connected 

Topics abonnieren

val topicPath = "/$lockID/Motor/direction" // Beispiel für ein Topic, dabei steht "lockID" für die ID des Schlosses
mqttClient.subscribe(topicPath, object : IMqttMessageListener {
   override fun messageArrived(topic: String?, message: MqttMessage?) {
      // Nachricht des Mqtt Servers
   }
}

Nachricht an den Mqtt Server schicken

val mqttMessage = MqttMessage()
mqttMessage.payload = message.toByteArray() // message = Die Nachricht die an den Topic geschickt werden sollen
mqttClient.publish(topic, mqttMessage)

Abmelden vom Server

mqttClient.disconnect()

Sichere Aufbewahrung der Logindaten[Bearbeiten]

Damit der Nutzer nicht jedesmal seine Logindaten eingeben muss wird Ihm die Möglichkeit gegeben die Logindaten auf dem Smartphone zu speichern. Dabei wird der Nutzername und das Password mit AES verschlüsselt.
Genutzte Bibliotheken sind Cipher zum generieren des Secret Keys und ent-/verschlüsseln der Daten, sowie KeyStore zum sicheren Aufbewahren des Secret Keys.

Generieren eines neuen SecretKeys und gleichzeitigem Speichern des Keys im KeyStore

private fun generateSecretKey(): SecretKey {
   val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
   val spec = KeyGenParameterSpec
      .Builder(keystoreAlias, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT) // keystoreAlias = "UnboundLock"
      .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
      .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
      .build()

   keyGenerator.init(spec)
   return keyGenerator.generateKey()
}

Abrufen des SecretKeys, entweder durch einen bereits erstellten SecretKey oder generieren eines neuen SecretKeys

private fun getSecretKey(): SecretKey {
   val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) }
   val secretKeyEntry = keyStore.getEntry(keystoreAlias, null) as? KeyStore.SecretKeyEntry

   return if (secretKeyEntry != null) {
      secretKeyEntry.secretKey
   } else {
      generateSecretKey()
   }
}

Verschlüsseln der Daten mithilfe des SecretKeys. Dabei wird ein Initialisierungsvektor (IV) erstellt, mit dem später die Nachricht wieder entschlüsselt werden kann (In Verbindung mit dem SecretKey)

fun encrypt(data: String): Pair<ByteArray, ByteArray> {
   val cipher = Cipher.getInstance("AES/GCM/NoPadding")
   cipher.init(Cipher.ENCRYPT_MODE, getSecretKey())
   return Pair(cipher.doFinal(data.toByteArray()), cipher.iv)
}

Entschlüsseln der Daten mithilfe der Nachricht, dem Initialisierungsvektor und dem SecretKey

fun decrypt(encrypted: ByteArray, iv: ByteArray): String {
   val cipher = Cipher.getInstance("AES/GCM/NoPadding")
   val spec = GCMParameterSpec(128, iv)
   cipher.init(Cipher.DECRYPT_MODE, getSecretKey(), spec)
   val decoded = cipher.doFinal(encrypted)
   return String(decoded, Charsets.UTF_8)
}

Kritik[Bearbeiten]

Zwar wurde ein funktionierender Prototyp zustande gebracht, der Sensorik, Aktorik und MQTT-Kommunikation vereint, doch ist er allemal noch ausbaufähig.

Mehr Funktionen[Bearbeiten]

Neben der zeitweiligen Direktnachricht wäre optional auch ein permanenter Text, über den z.B. Lieferanten oder unerwartete Gäste eine schnelle Inkenntnissetzung erhielten, denkbar.

Bisweilen schränkte uns insbesondere die verfügbare Pluralität an Pins des ESP32 ein, weshalb die Implementation der netzunabhängigen Steuerungen, des Tastenfeldes und RFID-Lesers, scheiterten. Solche benötigten allem voran ADC-Schnittstellen, die allerdings schnell von der WLAN-Funktionalität und den etwaigen anderen Verbrauchern am ESP32 belagert wurden.

Mangelhafte Netzkorrespondenz[Bearbeiten]

Vernetzte Schlosssysteme wissen um den anderen und können gemeinsam agieren (z.B. im Schleusenmodus) oder den Nutzer auf Dysfunktionen anderer Einheiten hinweisen.

Fehlendes Gehäuse[Bearbeiten]

Abgeschlossen fühlt sich ein Projekt erst an, wenn man die scharfen Kanten und die raue Haptik abschleift; dazu ist ein Gehäuse nahezu unerlässlich. Es verhüllt unansehnliche Stellen, die Elektronik zum Beispiel, und hebt Wichtiges wie den Bildschirm hervor - das, was den gemeinen Nutzer letztendlich für eine nahtlose User-Experience tangiert. Den Prototypen aber in eine läppische Schuhkartonbox zu plantieren, wirkt auch mehr wie ein liebloser Akt in der Not oder Unbekümmertheit, kann wohl aber nicht umgangen werden angesichts des Werkzeugmangels durch Corona.

Benutzerfreundlichkeit[Bearbeiten]

Im Falle, dass der Motor gehindert ist, eine Öffnungsbewegung auszuführen, wäre ein manuelle Entriegelungslösung angebracht; in Hinsicht auf unsere derzeitige Implementation der Übersetzung der Drehbewegung des Motors zum Schieben des Riegels über eine lange Schraube bzw. ein Gewinde ist das allerdings nicht möglich, ohne ein drastisches Sicherheitsrisiko darzustellen.

Auch das fehlende Gehäuse ausnehmend bleibt der derzeitige Prototyp installier-giftig. Bedeutet, dass einige elektrische Teilkomponenten und der Schlossriegel nur angbringbar sind, wenn irreversible Löcher in das Mauerwerk und die Tür gebohrt werden würden. Wie bereits in der Sektion "Fehlendes Gehäuse" angerissen, ließe sich dies durch eine andere Schlossvariante lösen; die Sensoren außerhalb könnten auch mit doppelseitigem Klebeband fixiert werden, sind sie nicht direkter Witterung ausgesetzt.

Stetiges Feedback bei Eingaben, Einstellungen auf der Anzeige und der App.