summaryrefslogtreecommitdiff
path: root/lib/data.dart
blob: 38fd56491cb95c5758516ae58ad4b9d2861be908 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';

const String brokerHostname = 'sia.xengineering.eu';
const int brokerPort = 1883;
const String topicPrefix = 'sia';

class AppState with ChangeNotifier {
  Map<String, bool> contacts = <String, bool>{};
  late final MqttServerClient _client;
  bool _brokerConnected = false;
  bool get brokerConnected => _brokerConnected;

  AppState() {
    _initMqtt();
  }

  @override
  void dispose() {
    _client.disconnect();
    super.dispose();
  }

  Future<void> _initMqtt() async {
    _client = MqttServerClient(
      brokerHostname,
      'sia_app_${DateTime.now().millisecondsSinceEpoch}',
    );

    _client.port = brokerPort;
    _client.keepAlivePeriod = 2;
    _client.autoReconnect = true;
    _client.disconnectOnNoResponsePeriod = 1;
    _client.logging(on: false);

    _client.onConnected = _onConnected;
    _client.onDisconnected = _onDisconnected;
    _client.onAutoReconnect = _onAutoReconnect;
    _client.onAutoReconnected = _onAutoReconnected;

    try {
      await _client.connect();
    } catch (e) {
      _client.disconnect();
      return;
    }

    _client.updates?.listen(_onMessage);
  }

  void _onConnected() {
    _client.subscribe('$topicPrefix/contact/+/state', MqttQos.exactlyOnce);
    _brokerConnected = true;
    notifyListeners();
  }

  void _onDisconnected() {
    _brokerConnected = false;
    notifyListeners();
  }

  void _onAutoReconnect() {
    _brokerConnected = false;
    notifyListeners();
  }

  void _onAutoReconnected() {
    _brokerConnected = true;
    notifyListeners();
  }

  void _onMessage(List<MqttReceivedMessage<MqttMessage>> messages) {
    for (final MqttReceivedMessage<MqttMessage> message in messages) {
      final String topic = message.topic;

      // format <prefix>/contacts/<address>/state
      final List<String> parts = topic.split('/');
      if (parts.length != 4 || parts[1] != 'contact' || parts[3] != 'state') {
        continue;
      }
      final String address = parts[2];

      final MqttPublishMessage payloadMessage =
        message.payload as MqttPublishMessage;
      final String payload =
        MqttPublishPayload.bytesToStringAsString(payloadMessage.payload.message);

      final bool? parsedState = _parseBool(payload);

      if (parsedState != null) {
        contacts[address] = parsedState;
        notifyListeners();
      }
    }
  }

  bool? _parseBool(String payload) {
    switch (payload.toLowerCase()) {
      case 'open':
        return true;
      case 'closed':
        return false;
      default:
        return null;
    }
  }
}