/* * Usurpation – wearable device main logic * * Copyright (C) 2019 Gediminas Jakutis * Copyright (C) 2019 Ramūnas Mažeikis * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #include "SSD1306Wire.h" #include "DejaVu_Sans_Mono_13.h" #include "device_network.h" #include "screen.h" #include "utils.h" #include "tlv.h" static const unsigned int internal_led = 2; static unsigned int led_state = 0; SSD1306Wire display(0x3c, 4, 5, GEOMETRY_128_32); static void init_OLED(void); unsigned int toggle_led(const int pin); static int wifi_connect(const char * const ssid, const char * const password, const char doblink, const int ledpin); static void blink_led(const int pin, const int ontime, const int offtime); void handle_tlv(const struct tlv *data); static struct progstate_t { int ip_print_count; struct display_status ds; struct tlv field; struct tlv_packet heartbeat; size_t bytes_read; char buf[MTU]; char hbcounter; } progstate; void setup(void) { extern const char * const ssid; extern const char * const password; struct tlv field; pinMode(internal_led, OUTPUT); toggle_led(internal_led); init_OLED(); display.fillCircle(32, 16, 12); display.display(); wifi_connect(ssid, password, 1, internal_led); udp_init(com_port); display.fillCircle(64, 16, 12); display.display(); discover_client(com_port); display.fillCircle(92, 16, 12); display.display(); progstate.ip_print_count = 5; tlv_init(&field, HEARTBEAT); field.data = strdup(heartbeat_device); field.head.size = sizeof(heartbeat_device); tlv_packet_init(&progstate.heartbeat); tlv_pack(&progstate.heartbeat, &field); tlv_packet_finalize(&progstate.heartbeat); tlv_destroy(&field); } void loop(void) { static const String devstr = "Device IP:"; static const String daemonstr = "Daemon IP:"; static String prefix; static IPAddress ip_to_print; static IPAddress *daemon_ip = NULL; #if 0 char *saveptr; #endif static unsigned int delta = 2000; /* sleep length to use (ms) */ delay(delta); if (!progstate.hbcounter) { udp_init_packet(com_port); udp_push(progstate.heartbeat.data, progstate.heartbeat.cursor + 1); udp_flush(); progstate.hbcounter = 2; } if (progstate.ip_print_count) { /* Initial display of ip's. */ if (!daemon_ip) { daemon_ip = get_daemon_address(); } prefix = (progstate.ip_print_count % 2) ? devstr : daemonstr; ip_to_print = (progstate.ip_print_count) ? WiFi.localIP() : *daemon_ip; display.clear(); display.drawString(0, 0, prefix); display.drawString(0, 16, ip_to_print.toString()); display.display(); progstate.ip_print_count--; } else { progstate.bytes_read = udp_get_data(progstate.buf, sizeof(progstate.buf)); if (progstate.bytes_read > 0) { tlv_get(progstate.buf, &progstate.field, NULL); handle_tlv(&progstate.field); #if 0 /* Dealing with tlv's one at a time. */ saveptr = progstate.buf; while (!(tlv_get(saveptr, &progstate.field, &saveptr))) { handle_tlv(&progstate.field); } #endif } display_update_scroll(&progstate.ds); } --progstate.hbcounter; } void handle_tlv(const struct tlv *in) { /* Currently just dealing with text. * */ switch (in->head.type) { case TEXT: display_status_init(&display, &progstate.ds, in->data); break; default: display.clear(); display.drawString(0, 0, "Fugg :DDD"); break; } } static void init_OLED(void) { display.init(); display.flipScreenVertically(); display.setTextAlignment(TEXT_ALIGN_LEFT); display.setFont((uint8_t *)DejaVu_Sans_Mono_13); } /* toggle the bult-in led and return current state */ unsigned int toggle_led(const int pin) { led_state = !led_state; /* as the cathode of the builtin diode is connected to the MCU's pin, * while the anode is connected to Vcc, to turn it off, we need to set * the pin to HIGH. */ digitalWrite(pin, led_state ? LOW : HIGH); return led_state; } static int wifi_connect(const char * const ssid, const char * const password, const char doblink, const int ledpin) { size_t i = 30; WiFi.forceSleepWake(); yield(); WiFi.persistent(0); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); do { if (doblink) { blink_led(ledpin, 250, 250); } else { delay (500); } } while (WiFi.status() != WL_CONNECTED); return 0; } static void blink_led(const int pin, const int ontime, const int offtime) { toggle_led(pin); delay(ontime); toggle_led(pin); delay(offtime); }