#include #include #include #include "motor.h" #include "secrets.h" #define INPUT_SIZE 4 enum state { STATE_CONNECTING, STATE_LOGGED_OUT, STATE_LOGGED_IN, STATE_INPUT_PASSCODE, }; enum state current_state; char input_code[INPUT_SIZE + 1]; int user_id; MKRIoTCarrier carrier; WiFiSSLClient wifi_client; MqttClient mqtt_client(wifi_client); // Motor control variables int motor_count = 0; int motor_count_max = 64; uint32_t red_led_color = carrier.leds.Color(255, 0, 0); uint32_t green_led_color = carrier.leds.Color(0, 255, 0); uint32_t blue_led_color = carrier.leds.Color(0, 0, 255); bool is_input_empty() { for (int i = 0; i < INPUT_SIZE; i++) { if (input_code[i]) return false; } return true; } bool is_input_full() { for (int i = 0; i < INPUT_SIZE; i++) { if (!input_code[i]) return false; } return true; } void change_state(enum state new_state) { // Initialize state switch (new_state) { case STATE_INPUT_PASSCODE: input_code[0] = '\0'; input_code[1] = '\0'; input_code[2] = '\0'; input_code[3] = '\0'; input_code[4] = '\0'; break; } current_state = new_state; draw_state(); } void draw_state() { // Reset carrier.display.fillScreen(0x000); carrier.leds.fill(0, 0, 5); carrier.leds.setBrightness(5); switch (current_state) { case STATE_CONNECTING: carrier.display.setCursor(20, 100); carrier.display.setTextSize(3); carrier.display.print("Connecting.."); break; case STATE_LOGGED_OUT: carrier.display.setCursor(15, 100); carrier.display.setTextSize(2); carrier.display.print("Press Green Button"); carrier.leds.fill(green_led_color, 2, 1); break; case STATE_INPUT_PASSCODE: if (is_input_empty()) { carrier.display.setCursor(50, 100); carrier.display.setTextSize(2); carrier.display.print("Please enter"); carrier.display.setCursor(80, 120); carrier.display.print("passcode"); } else { carrier.display.setCursor(50, 100); carrier.display.setTextSize(3); for (int i = 0; i < INPUT_SIZE; i++) { char ch = input_code[i]; if (!ch) ch = '_'; carrier.display.print(ch); carrier.display.print(' '); } } carrier.leds.fill(blue_led_color, 0, 2); carrier.leds.fill(red_led_color, 2, 1); carrier.leds.fill(blue_led_color, 3, 2); break; case STATE_LOGGED_IN: carrier.display.setCursor(40, 100); carrier.display.setTextSize(3); carrier.display.print("Logged in"); carrier.leds.fill(green_led_color, 2, 1); carrier.leds.fill(red_led_color, 4, 1); break; } carrier.leds.show(); } void setup() { Serial.begin(9600); Serial.println("Started"); carrier.noCase(); carrier.begin(); carrier.display.init(240, 240); motor_setup(); pinMode(TFT_BACKLIGHT, OUTPUT); digitalWrite(TFT_BACKLIGHT, HIGH); change_state(STATE_CONNECTING); Serial.println("Connecting to WiFi..."); if (wifi_enterprise) WiFi.beginEnterprise(wifi_ssid, wifi_username, wifi_password); else WiFi.begin(wifi_ssid, wifi_password); while (WiFi.status() != WL_CONNECTED) delay(1000); Serial.println("Connected to WiFi, connecting to MQTT..."); mqtt_client.setUsernamePassword(mqtt_username, mqtt_password); if (!mqtt_client.connect(mqtt_server, 8883)) { Serial.print("MQTT connection failed with error code: "); Serial.println(mqtt_client.connectError()); return; } Serial.println("Connected to MQTT"); carrier.Buzzer.beep(); mqtt_client.subscribe("dispense"); mqtt_client.subscribe("login"); change_state(STATE_LOGGED_OUT); } void loop() { carrier.Buttons.update(); // Rotate motor if needed if (motor_count) { motor_clockwise(); motor_count--; } // Receive MQTT messages int message_size = mqtt_client.parseMessage(); if (message_size) { String topic = mqtt_client.messageTopic(); Serial.print("Got message with topic: "); Serial.println(topic); // Parse message char *message = (char *)malloc(message_size + 1); for (int i = 0; i < message_size && mqtt_client.available(); i++) { message[i] = (char)mqtt_client.read(); } message[message_size] = '\0'; Serial.print("and payload: "); Serial.println(message); // Check topic if (topic == "dispense") { Serial.println("Dispensing..."); // Start rotating motor motor_count += motor_count_max; } else if (topic == "login") { Serial.println("Logged in"); if (sscanf(message, "%d", &user_id) > 0) { change_state(STATE_LOGGED_IN); } else { change_state(STATE_INPUT_PASSCODE); } } free(message); } touchButtons buttons[] = { TOUCH0, TOUCH1, TOUCH3, TOUCH4 }; char input_characters[] = "1234"; switch (current_state) { case STATE_LOGGED_OUT: if (carrier.Buttons.onTouchDown(TOUCH2)) { change_state(STATE_INPUT_PASSCODE); } break; case STATE_INPUT_PASSCODE: if (carrier.Buttons.onTouchDown(TOUCH2)) { if (is_input_empty()) { change_state(STATE_LOGGED_OUT); } else { for (int i = INPUT_SIZE - 1; i >= 0; i--) { if (input_code[i]) { input_code[i] = '\0'; draw_state(); break; } } } } for (int i = 0; i < sizeof(buttons) / sizeof(buttons[0]); i++) { if (carrier.Buttons.onTouchDown(buttons[i])) { for (int j = 0; j < INPUT_SIZE; j++) { if (!input_code[j]) { input_code[j] = input_characters[i]; break; } } if (is_input_full()) { mqtt_client.beginMessage("login_request"); mqtt_client.print(input_code); mqtt_client.endMessage(); } draw_state(); break; } } break; case STATE_LOGGED_IN: if (carrier.Buttons.onTouchDown(TOUCH2)) { char *user_id_str = (char *)malloc(4); snprintf(user_id_str, 4, "%d", user_id); mqtt_client.beginMessage("dispense_request"); mqtt_client.print(user_id_str); mqtt_client.endMessage(); free(user_id_str); } if (carrier.Buttons.onTouchDown(TOUCH4)) { change_state(STATE_LOGGED_OUT); } break; } delay(2); }