hw10 done, please check
This commit is contained in:
parent
babfc83f4a
commit
2bb1147728
2 changed files with 187 additions and 0 deletions
2
build.js
2
build.js
|
@ -188,6 +188,7 @@ function toc(str) {
|
||||||
if (token.heading.indexOf("Ex -") >= 0) {
|
if (token.heading.indexOf("Ex -") >= 0) {
|
||||||
token.heading = token.heading.replace("Ex -", `<span class='task'>${task_count}.</span> `);
|
token.heading = token.heading.replace("Ex -", `<span class='task'>${task_count}.</span> `);
|
||||||
task_count++;
|
task_count++;
|
||||||
|
if (task_count === 13) task_count++; // skip hands-on
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a "slugified" id for linking
|
// Create a "slugified" id for linking
|
||||||
|
@ -459,6 +460,7 @@ renderer.heading = function (text, level, raw, slugger) {
|
||||||
if (text.indexOf("Ex -") >= 0) {
|
if (text.indexOf("Ex -") >= 0) {
|
||||||
text = text.replace("Ex -", `<span class='task'>${task_count}.</span> `);
|
text = text.replace("Ex -", `<span class='task'>${task_count}.</span> `);
|
||||||
task_count++;
|
task_count++;
|
||||||
|
if (task_count === 13) task_count++; // skip hands-on
|
||||||
}
|
}
|
||||||
|
|
||||||
// let sec = "<section>"
|
// let sec = "<section>"
|
||||||
|
|
|
@ -1393,8 +1393,193 @@ Whenever you have a connector you couple together the components and different c
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1. The smart device protocol libraries `HAP-Java` and `paho.mqtt.java` play the role of adapters in the diagram of my architecture. The two components are highlighted in the diagram <span style="background-color: #CCCCCC">like this</span>.
|
||||||
|
2. The mismatch these adapters solve is between the state logic of the devices as handled by the SmartHut Users and Devices component and the way these states are represented and triggered in the MQTT and HomeKit protocol. The two protocol libraries act as a translation layer between the Java runtime of the Users and Devices component and the communication stack required by both protocols.
|
||||||
|
3. The `Homekit Device Wrapper` and `MQTT Device Wrapper` have been introduced in the diagram.
|
||||||
|
4. As SmartHut should handle by design different IoT protocols, no standard interfaces could play a role in the architecture. The wrappers (and in particular the _SmartHut to \[library\]_) adapters) I introduced aim to create a common ground between IoT protocols to handle the devices in a standardized fashion whitin SmartHut.
|
||||||
|
5. One important coupling facet decision between in the architecture is the discovery coupling between the web "engine" components. When deploying, I either aim to have a static configuration file where all Web Interface root endpoints are enumerated (one per component) to allow both a monolith and polylith installation of SmartHut according to the user's needs (an example of a project that allows this kind of decision at deployment is the Matrix protocol implementation [Dendrite](https://github.com/matrix-org/dendrite)).
|
||||||
|
6. Here I provide examples of how the adapters in the MQTT Wrapper and Homekit wrapper adapt
|
||||||
|
the communication between the SmartHut Users and Devices engine component and the respective protocols. I envision a common interface specification for both protocols, enumerating the actions of each smart device. Here's an example for a smart light with only on/off capabilities:
|
||||||
|
|
||||||
|
```java
|
||||||
|
interface Light {
|
||||||
|
Future<boolean> getStatus();
|
||||||
|
Future<Void> setStatus(boolean turnOn);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, here's a high level implementation for the MQTT protocol, which is code to be included in the SmartHut to paho.mqtt.java adapter:
|
||||||
|
|
||||||
|
```java
|
||||||
|
class MQTTLight extends Light {
|
||||||
|
private final MqttClient client;
|
||||||
|
private final String deviceTopic;
|
||||||
|
|
||||||
|
public MQTTLight(@Inject MqttClient client, String deviceTopic) {
|
||||||
|
this.client = client;
|
||||||
|
this.deviceTopic = deviceTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Future<boolean> getStatus() {
|
||||||
|
return client.subscribe(deviceTopic /* get status message */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Future<Void> setStatus(boolean turnOn) {
|
||||||
|
return client.publish(deviceTopic, new MqttMessage(turnOn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
and here's a high level implementation for the Homekit protocol, to be included in the SmartHut to HAP-java adapter:
|
||||||
|
|
||||||
|
```java
|
||||||
|
class HAPLight extends Light {
|
||||||
|
private final LightBulbAccessory accessory;
|
||||||
|
|
||||||
|
public HAPLight(LightBulbAccessory accessory) {
|
||||||
|
this.accessory = accessory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HAPLight discover(String deviceId) {
|
||||||
|
/** here create the lightbulb accessory object from the given
|
||||||
|
device id, call constructor */
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Future<boolean> getStatus() {
|
||||||
|
return accessory.getLightbulbPowerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Future<Void> setStatus(boolean turnOn) {
|
||||||
|
return accessory.setLightBulbPowerState(turnOn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
7. Coupling between the engine components of Smarthut would be to introduce Zeroconf clients and servers in all engine components and allow auto-discovery in an initial setup phase, which would delay discovery coupling at runtime an allow for more flexible deployments. However, this would slightly complicate the implementation of the frontend as UDP/broadcast connections are harder to implement in a web-based interface.
|
||||||
|
|
||||||
|
|
||||||
|
```puml
|
||||||
|
@startuml
|
||||||
|
skinparam componentStyle rectangle
|
||||||
|
|
||||||
|
!include <tupadr3/font-awesome/database>
|
||||||
|
|
||||||
|
title Smarthut.sm Logical View
|
||||||
|
|
||||||
|
interface " " as DIF
|
||||||
|
interface " " as TF
|
||||||
|
interface " " as SCF
|
||||||
|
interface " " as SHAF
|
||||||
|
interface " " as SZAF
|
||||||
|
|
||||||
|
component "Homekit Device Wrapper" as IOTHK {
|
||||||
|
interface " " as HDF
|
||||||
|
interface " " as HSF
|
||||||
|
interface " " as HAPF
|
||||||
|
|
||||||
|
[HomeKit smart device] as HD <<user provided>>
|
||||||
|
[HomeKit smart sensor] as HS <<user provided>>
|
||||||
|
[HAP-java] as HAP <<external>> #CCCCCC
|
||||||
|
[SmartHut to HAP-java adapter] as SHA
|
||||||
|
|
||||||
|
HAP--HAPF
|
||||||
|
HD--HDF
|
||||||
|
HS--HSF
|
||||||
|
HAPF)--SHA
|
||||||
|
SHA--SHAF
|
||||||
|
}
|
||||||
|
|
||||||
|
component "MQTT Device Wrapper" as IOTMQ {
|
||||||
|
interface " " as ZDF
|
||||||
|
interface " " as ZSF
|
||||||
|
interface " " as ZIGF
|
||||||
|
|
||||||
|
[MQTT smart device] as ZD <<user provided>>
|
||||||
|
[MQTT smart sensor] as ZS <<user provided>>
|
||||||
|
[paho.mqtt.java] as ZIG <<external>> #CCCCCC
|
||||||
|
[SmartHut to paho.mqtt.java adapter] as SZA
|
||||||
|
|
||||||
|
ZD--ZDF
|
||||||
|
ZS--ZSF
|
||||||
|
ZIG--ZIGF
|
||||||
|
SZA--SZAF
|
||||||
|
ZIGF)--SZA
|
||||||
|
}
|
||||||
|
|
||||||
|
component "User Interface" as UIC {
|
||||||
|
interface " " as WSCF
|
||||||
|
|
||||||
|
[User Interface] as UI
|
||||||
|
[WebSockets API (JavaScript)] <<external>> as WSC
|
||||||
|
|
||||||
|
WSCF)--UI
|
||||||
|
WSC--WSCF
|
||||||
|
}
|
||||||
|
|
||||||
|
component "Users and Devices" as DEV {
|
||||||
|
interface " " as DIDBF
|
||||||
|
|
||||||
|
interface " " as WSSF
|
||||||
|
|
||||||
|
[Device Engine] as DI
|
||||||
|
|
||||||
|
note left of DI: Already implemented using Spring Boot
|
||||||
|
|
||||||
|
[javax.websocket API] as WSS <<external>>
|
||||||
|
[User and Device DB <$database{scale=0.33}> (PostgreSQL)] <<external>> as DIDB
|
||||||
|
|
||||||
|
HDF )-- HAP
|
||||||
|
HSF )-- HAP
|
||||||
|
ZDF )-- ZIG
|
||||||
|
ZSF )-- ZIG
|
||||||
|
|
||||||
|
DI--(WSSF
|
||||||
|
WSSF--WSS
|
||||||
|
SHAF )-- DI
|
||||||
|
SZAF )-- DI
|
||||||
|
DIDBF-DIDB
|
||||||
|
DI -( DIDBF
|
||||||
|
}
|
||||||
|
|
||||||
|
component "Triggers and Automations" as TRIG {
|
||||||
|
interface " " as TDBF
|
||||||
|
|
||||||
|
[Trigger and Automation Engine] as T
|
||||||
|
[Trigger and Automation DB <$database{scale=0.33}> (PostgreSQL)] <<external>> as TDB
|
||||||
|
|
||||||
|
TDBF-TDB
|
||||||
|
T -( TDBF
|
||||||
|
}
|
||||||
|
|
||||||
|
component "Scenes" as SCENE {
|
||||||
|
interface " " as SCDBF
|
||||||
|
|
||||||
|
[Scene Engine] as SC
|
||||||
|
[Scene DB <$database{scale=0.33}> (PostgreSQL)] <<external>> as SCDB
|
||||||
|
|
||||||
|
SCDBF-SCDB
|
||||||
|
SC -( SCDBF
|
||||||
|
}
|
||||||
|
|
||||||
|
DI--DIF
|
||||||
|
TF--T
|
||||||
|
SCF--SC
|
||||||
|
WSS <..> WSC: WebSocket protocol (RFC 6455)
|
||||||
|
DI --( TF
|
||||||
|
T --( SCF
|
||||||
|
DIF )-- SC
|
||||||
|
DIF )-- UI
|
||||||
|
UI --( SCF
|
||||||
|
UI --( TF
|
||||||
|
|
||||||
|
skinparam monochrome true
|
||||||
|
skinparam shadowing false
|
||||||
|
skinparam defaultFontName Courier
|
||||||
|
@enduml
|
||||||
|
```
|
||||||
|
|
||||||
# Ex - Physical and Deployment Views
|
# Ex - Physical and Deployment Views
|
||||||
|
|
||||||
|
|
Reference in a new issue