Newer
Older
VizBlocks(char* id, char* ssid="VizBlocksNet", char* wifi_pass="VizBlocksAP",
char* server="172.20.10.8",int port=1883) : _id(id), _server(server), _port(port), _ssid(ssid), _wifi_pass(wifi_pass) {} ;
void VizBlocks::add(Behaviour *b) {
_behaviours.add(b);
};
void VizBlocks::serial_command() {
if( Serial.available() ) {
String cmd = Serial.readStringUntil('\n');
cmd.replace("\r", "");
Serial.println(process(cmd));
}
};
void VizBlocks::generateCapabilitiesJSON() {
String head = "{\"id\":\"" + String(_id) + "\",\"Behaviour\":{";
for (int i = 0; i < _behaviours.get_num_behaviours(); i++) {
Behaviour* b = _behaviours.get_by_num(i);
String args = b->args();
String body = "\"name\":\"" + b->name() + "\",\"args\":\"" + args + "\"}}";
String str = head + body;
capabilitiesJSON[i] = str;
}
};
char * VizBlocks::getId() {
return _id;
};
void VizBlocks::MQTT_connect() {
int8_t ret;
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
// Stop if already connected.
if (_mqtt->connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t retries = 3;
while ((ret = _mqtt->connect()) != 0) { // connect will return 0 for connected
Serial.println(_mqtt->connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
_mqtt->disconnect();
delay(5000); // wait 5 seconds
retries--;
if (retries == 0) {
// basically die and wait for WDT to reset me
while (1);
}
}
Serial.println("MQTT Connected!");
};
int VizBlocks::input_event(String input) {
return process(input);
};
void VizBlocks::run() {
int loop_start_time = millis();
serial_command();
if( _wifi ) { mqtt_command(); }
if( _active ) {
_active -> update();
if( ! _active->is_running() ) { _active = nullptr; }
}
for (int i = 0; i < NUM_BACKGROUND_BEHAVIOURS; i++) {
if( _background[i] ) {
_background[i] -> update();
if( !_background[i] -> is_running() ) { _background[i] = nullptr; }
}
}
int loop_time_taken = millis()-loop_start_time;
if( loop_time_taken < _loop_time ) {
delay( _loop_time - loop_time_taken );
}
};
void VizBlocks::init() {
Serial.setTimeout(100);
Serial.println();
Serial.println(F("VizBlocks Node starting up"));
Serial.println("Initialising " + String(_id));
if( _wifi ) {
WiFi.mode(WIFI_STA);
WiFi.setSleepMode(WIFI_NONE_SLEEP);
// Connect to WiFi access point.
Serial.println();
Serial.print("Connecting to ");
Serial.println(_ssid);
WiFi.begin(_ssid, _wifi_pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: "); Serial.println(WiFi.localIP());
// Done Wifi
// Setup MQTT
_client = new WiFiClient();
_mqtt = new Adafruit_MQTT_Client(_client, _server, _port, "" /* mqttt username */, "" /* mqtt pass*/);
_device_subscription = new Adafruit_MQTT_Subscribe(_mqtt, _id);
_announce = new Adafruit_MQTT_Publish(_mqtt, "announce");
_my_announce_channel = String("announce/") + String(_id);
_my_announce = new Adafruit_MQTT_Publish(_mqtt, _my_announce_channel.c_str());
// Setup MQTT subscription for this device
_mqtt->subscribe(_device_subscription);
// This *would* setup a callback, but we're not doing this right now...
//_device_subscription->setCallback(test_callback);
MQTT_connect();
}
generateCapabilitiesJSON();
announce_capabilities();
Serial.println("Init finished");
};
void VizBlocks::announce(String doc) {
if( _wifi ) { _my_announce->publish(doc.c_str()); }
Serial.print("-->");
Serial.println(doc);
};
void VizBlocks::announce_capabilities() {
String doc;
if( _wifi ) {
if( ! _announce->publish(_id) ) { Serial.println("Couldn't make announcement"); }
}
for( int i = 0; i < _behaviours.get_num_behaviours(); i++ ) {
doc = capabilitiesJSON[i];
announce(doc);
}
};
void VizBlocks::set_wifi(boolean v) { _wifi = v; };
void VizBlocks::setID(char* id) {
_id = id;
};
void VizBlocks::mqtt_command() {
MQTT_connect(); //ensure connection
Adafruit_MQTT_Subscribe *subscription;
while ((subscription = _mqtt->readSubscription(50))) {
if (subscription == _device_subscription) {
Serial.print(F("Got: "));
Serial.println((char *)_device_subscription->lastread);
Serial.println(process((char *)_device_subscription->lastread));
}
}
};
int VizBlocks::process_command(String command, String args) {
Serial.println("Processing <"+command+"> <"+args+">");
Behaviour* b = _behaviours.get(command);
if(b) {
// Stop whatever behaviour is running in the active slot.
if( _active ) { _active->stop(); }
Serial.println( "Found behaviour: <"+command+">" );
if ( b->is_background() ) {
// If this behaviour is already running in the background, refresh it and move on.
for (int i = 0; i < NUM_BACKGROUND_BEHAVIOURS; i++) {
if ( _background[i] ) {
if ( b->name() == _background[i]->name() ) {
return( b->start(args) );
}
}
}
// Else, if there is space for another background behaviour, start it running.
for (int i = 0; i < NUM_BACKGROUND_BEHAVIOURS; i++) {
if ( !_background[i] ) {
_background[i] = b;
return( b->start(args) );
}
}
return "Couldn't run command: " + command + ". Background behaviours full.";
}
_active = b;
return( b->start(args) );
} else {
return "Couldn't process command: " + command;
}
};
int VizBlocks::process(String input) {
if (!(input.indexOf("<") >= 0 || input.indexOf(">") >= 0 || input.indexOf("-") >= 0)) {
int index = input.indexOf(" ");
String command = "";
String args = "";
if( index ) {
command = input.substring(0,index);
args = input.substring(index+1);
} else {
command = input;
}
return process_command(command, args);
}
};
void VizBlocks::command_callback(char *data, uint16_t len) {
Serial.println("Got command: ");
Serial.println(data);
};