Komunikacja MQTT
Dane serwera deweloperskiego
- Adres: vemmio.dev
- Port: 1883
- Nazwa użytkownika: vemmio
- Hasło użytkownika: Q4xF6KYfvGgrMDmjcaBTiYuPixTxaCox8regAAdqAmCePbkFw7CR8Dfd8nEPhRuL
Definicje protobuf
Informacje ogólne
Urządzenie wysyła okresowo komunikat PresenceNotification na temat presence/AA:BB:CC:DD:EE:FF.
message PresenceNotification {
string mac = 1;
string version = 2;
string git_commit = 3;
string build_time = 4;
string firmware_version = 5;
}
Po otrzymaniu tej informacji serwer uznaje urządzenie za połączone.
Serwer sprawdza co 15 sekund czy ma aktualne informacje o urządzeniu. Jeśli ostatnia aktualizacja informacji nie wystąpiła w ciągu ostatnich 30 sekund, serwer uznaje urządzenie za rozłączone.
Raporty
Urządzenie wysyła komunikaty GatewayReport na temat reports/AA:BB:CC:DD:EE:FF.
Komunikat zawiera identyfikator urządzenia i treść raportu urządzenia.
W treści raportu urządzenia przesyła dane identyfikacyjne urządzenia, chwilę czasową wystąpienia raportu oraz treść raportu odpowiednią dla typu urządzenia.
message DeviceReport {
DeviceMetadata metadata = 1;
google.protobuf.Timestamp timestamp = 2;
oneof report {
SwitchReport switch = 3;
...
TemperatureReport temperature = 12;
...
WiFiReport wifi = 28;
...
}
}
Dane identyfikacyjne uzupełniamy w zależności od rodzaju urządzenia.
Przykładowo dla przekaźnika i czujnika temperatury WiFi wykorzystamy MQTTMetadata.
W celu przesłania informacji o sile sygnału WiFi uzupełnimy WiFiMetadata.
W przypadku informacji o sieci WiFi, dane identyfikacyjne nie zawierają szczegółów.
Dane identyfikacyjne urządzenia WiFi zawierają identyfikator urządzenia zakodowany do tablicy bajtów w sposób, który znać musi tylko urządzenie.
W przypadku prostych urządzeń identyfikator urządzenia może być pusty.
Jeśli jednak urządzenie będzie zawierało powielające się funkcje (np. dwa przekaźniki) identyfikator urządzenia musi zostać uzupełniony, aby możliwa była jego identyfikacja.
Przykładowy raport przekaźnika zawiera informację o jego stanie.
message SwitchReport {
SwitchValue value = 1;
}
enum SwitchValue {
SWITCH_UNKNOWN = 0;
SWITCH_ON = 1;
SWITCH_OFF = 2;
}
W skład raportu czujnika temperatury wchodzą wartość i odpowiadającej jej jednostka.
message TemperatureReport {
Unit unit = 1;
double value = 2;
}
enum Unit {
UNKNOWN = 0;
CELSIUS = 1;
FAHRENHEIT = 2;
...
}
Sterowanie
Sterowanie realizowane jest w modelu synchronicznym — żądanie/odpowiedź.
sequenceDiagram
actor U as Użytkownik
participant S as Serwer
participant B as Broker
participant D as Urządzenie
D->>B: subskrypcja<br/>commands/AA:BB:CC:DD:EE:FF
U->>S: włącz przekaźnik
S->>B: subskrypcja $response_topic$
S->>B: publikacja żądania mqtt_req<br/>commands/AA:BB:CC:DD:EE:FF
B->>D: przekazanie żądania mqtt_req
D->>B: publikacja potwierdzenia ACK
D->>D: włączenie przekaźnika
alt włączenie zakończone sukcesem
D->>B: publikacja odpowiedzi typu DATA
else włączenie nie powiodło się
D->>B: publikacja odpowiedzi typu ERROR
end
B->>S: przekazanie odpowiedzi
Opis kroków na przykładzie próby włączenia przekaźnika.
-
Urządzenie subskrybuje się na temacie
commands/AA:BB:CC:DD:EE:FF. -
Użytkownika zainicjował chęć włączenia przełącznika Z-Wave.
-
Serwer subskrybuje się na temacie o losowej nazwie, dalej będziemy się do niego odwoływać przez zwrot
$response_topic. -
Serwer przygotowuje paczkę danych (
mqttreq) żądania włączenia przekaźnika.
metadata := &vemmiopb.DeviceMetadata{
Metadata: &vemmiopb.DeviceMetadata_Mqtt{
Mqtt: &vemmiopb.MQTTMetadata{},
},
}
data := &vemmiopb.CommandRequestData{
Data: &vemmiopb.CommandRequestData_SwitchOn{
SwitchOn: &vemmiopb.SwitchRequest{
Metadata: metadata,
},
},
}
req := &pb.CommandRequest{
Method: "Switch/SwitchOn",
Type: vemmiopb.CommandRequestType_REQUEST_TYPE_DATA,
Data: data,
}
mqttreq := &vemmiopb.MQTTCommandRequest{
Request: req,
ResponseTopic: "$response_topic",
}
-
Serwer publikuje paczkę danych (
mqttreq) na tematcommands/AA:BB:CC:DD:EE:FF. -
Urządzenie odbiera paczkę danych (
mqttreq). -
Urządzenie publikuje potwierdzenie otrzymania żądania na temacie
$response_topic.
-
Urządzenie na podstawie wartości pola
Methodrozpoznaje typ żądania i je obsługuje. -
Urządzenie publikuje odpowiedź na wysłane żądanie na temacie
$response_topic.
W przypadku pomyślnego wykonania żądania, serwer oczekuje na odpowiedź zawierającą rezultat wykonania żądania (dla przekaźników rezultat nie zawiera danych).
reply := &pb.CommandReply{
Type: vemmiopb.CommandReplyType_REPLY_TYPE_DATA,
Data: &pb.CommandReplyData{
Data: &pb.CommandReplyData_SwitchOn{
SwitchOn: &pb.SwitchResponse{},
},
},
}
W przypadku błędu wykonania żądania, serwer oczekuje na odpowiedź zawierającą komunikat o błędzie.
reply := &vemmiopb.CommandReply{
Type: vemmiopb.CommandReplyType_REPLY_TYPE_ERROR,
Error: &vemmiopb.CommandReplyError{
Message: "...",
},
}
Żądania niewymagające odpowiedzi
Struktura CommandRequest została rozszerzona o listę opcji, która pozwala serwerowi zakomunikować
oczekiwania dotyczące odpowiedzi.
message CommandRequest {
string method = 1;
CommandRequestType type = 2;
CommandRequestData data = 3;
bytes payload = 4;
repeated CommandRequestOption options = 5;
}
enum CommandRequestOption {
REQUEST_OPTION_UNSPECIFIED = 0;
REQUEST_OPTION_NOACK = 1;
REQUEST_OPTION_NORESPONSE = 2;
}
Obsługiwane opcje i ich znaczenie:
REQUEST_OPTION_NOACK- serwer nie czeka na potwierdzenie otrzymania żądaniaREQUEST_OPTION_NORESPONSE- serwer nie czeka na odpowiedź zawierającą rezultat wykonania żądania