diff options
-rw-r--r-- | src/server/main.c | 194 | ||||
-rw-r--r-- | src/tempmodule/main.ino | 184 |
2 files changed, 378 insertions, 0 deletions
diff --git a/src/server/main.c b/src/server/main.c new file mode 100644 index 0000000..902898e --- /dev/null +++ b/src/server/main.c @@ -0,0 +1,194 @@ +/* + * An unnamed project – client module + * + * Copyright (C) 2017 Gediminas Jakutis + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/udp.h> +#include <poll.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <arpa/inet.h> +#include <ncurses.h> +#include <stddef.h> +#include <stdlib.h> +#include <time.h> + +static void init(const unsigned int port, int *sock); +static int getpacket(char *data, size_t buffsize, int *sock, struct sockaddr_in *sender); +static void draw_idle(void); +static void draw_busy(const char * const data); +static float digest_mpu_temp(const short int rawdata); +static float digest_thermistor_voltage(const short int rawdata); + +int main(void) +{ + static const char servermagic[] = "I love coffee!"; + static const char clientmagic[] = "I love tea!"; + struct sockaddr_in srvaddr = {0}; + char buff[9001] = {0}; + int sock; + int pstatus; + struct timespec lastreply; + struct timespec now; + + init(2191, &sock); + + clock_gettime(CLOCK_MONOTONIC_RAW, &now); + lastreply = now; + lastreply.tv_sec -= 5; + + do { + clock_gettime(CLOCK_MONOTONIC_RAW, &now); + pstatus = getpacket(buff, sizeof(buff), &sock, &srvaddr); + + switch (pstatus) { + case 0: + if ((now.tv_sec - lastreply.tv_sec) >= 5) { + draw_idle(); + } + break; + case 1: + lastreply = now; + if (buff[0] == 'I') { + if (!(strcmp(buff, servermagic))) { + sendto(sock, clientmagic, sizeof(clientmagic), + MSG_DONTWAIT, (struct sockaddr *) &srvaddr, sizeof(srvaddr)); + } + draw_idle(); + continue; + } + draw_busy(buff); + break; + default: + ; /* noop */ + } + } while (getch() != 'q' && pstatus >= 0); + + close(sock); + endwin(); + + return 0; +} + +static void init(const unsigned int port, int *sock) +{ + struct sockaddr_in bindaddress = {0}; + + bindaddress.sin_family = AF_INET; + bindaddress.sin_port = htons(port); + *sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + bind(*sock, (struct sockaddr*) &bindaddress, sizeof(bindaddress)); + + initscr(); + nodelay(stdscr, 1); + noecho(); +} + +static int getpacket(char *data, size_t buffsize, int *sock, struct sockaddr_in *sender) +{ + static struct pollfd pfd = {0}; + int ret; + socklen_t sender_len = sizeof(*sender); + + if (!pfd.fd) { + pfd.fd = *sock; + pfd.events = POLLIN; + pfd.revents = 0; + } + + ret = poll(&pfd, 1, 25); + if (ret <= 0) { + return ret; + } + if (pfd.revents & POLLIN) { + recvfrom(*sock, data, buffsize, MSG_DONTWAIT, (struct sockaddr *) sender, &sender_len); + ret = 1; + } else { + ret = 0; + } + + return ret; +} + +static void draw_idle(void) +{ + move(0, 0); + clrtoeol(); + printw("sequence: [waiting for ESP8266...]"); + move(1, 0); + clrtoeol(); + mvprintw(1, 0, "mpu temp: [waiting for ESP8266...]"); + move(2, 0); + clrtoeol(); + mvprintw(2, 0, "thermistor voltage: [waiting for ESP8266...]"); + move(3, 0); + clrtoeol(); + mvprintw(3, 0, "press 'q' to exit"); + refresh(); +} + +static void draw_busy(const char * const data) +{ + unsigned int sequence; + short int mpu_data; + short int thermistor_data; + float mpu_temp; + float thermistor_voltage; + + memcpy(&sequence, data + 2, sizeof(sequence)); + memcpy(&mpu_data, data + 6, sizeof(mpu_data)); + memcpy(&thermistor_data, data + 8, sizeof(mpu_data)); + mpu_temp = digest_mpu_temp(mpu_data); + thermistor_voltage = digest_thermistor_voltage(thermistor_data); + + move(0, 0); + clrtoeol(); + printw("sequence: %u", sequence); + move(1, 0); + clrtoeol(); + mvprintw(1, 0, "mpu temp: %.3fC", mpu_temp); + move(2, 0); + clrtoeol(); + mvprintw(2, 0, "thermistor voltage: %.3fV", thermistor_voltage); + move(3, 0); + clrtoeol(); + mvprintw(3, 0, "press 'q' to exit"); + refresh(); +} + +static float digest_mpu_temp(const short int rawdata) +{ + float ret; + + ret = rawdata / 340.0f + 36.53f; + + return ret; +} + +static float digest_thermistor_voltage(const short int rawdata) +{ + float ret; + + ret = rawdata * 0.003222656f; + + return ret; +} diff --git a/src/tempmodule/main.ino b/src/tempmodule/main.ino new file mode 100644 index 0000000..cdaa874 --- /dev/null +++ b/src/tempmodule/main.ino @@ -0,0 +1,184 @@ +/* + * An unnamed project – esp8266 module + * + * Copyright (C) 2017 Gediminas Jakutis + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <ESP8266WiFi.h> +#include <WiFiUdp.h> +#include <Wire.h> +#include <stddef.h> +#include <string.h> + +static const unsigned int iled = 2; +static const unsigned int analog = A0; +static const int port = 2191; +static const int mpu_addr = 0x68; +static char udppacketbuffer[32] = {0}; +static char *udppacketcursor = NULL; +IPAddress ip; +WiFiUDP Udp; + +static void sleep(void); +static void udp_init_packet(IPAddress ip, const int port); +static void udp_push(const void * const data, const size_t size); +static int udp_flush(void); +static void mpu_wakeup(const int i2caddr); +static void 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); +static void discover_client(void); +static void discard(int a); + +void setup(void) +{ + static const char * const ssid = "SSID"; + static const char * const password = "password"; + + pinMode(iled, OUTPUT); + wifi_connect(ssid, password, 1, iled); + Udp.begin(port); + Wire.begin(); + mpu_wakeup(mpu_addr); + discover_client(); +} + +void loop(void) +{ + static unsigned int ticker = 0; + static unsigned char firstrun = 0; + short int data; + char *dataptr; + size_t i; + + Wire.beginTransmission(mpu_addr); + Wire.write(0x3b); + Wire.endTransmission(0); + Wire.requestFrom(mpu_addr, 14, 1); + + udp_init_packet(ip, port); + + dataptr = (char*) &data; + data = 0; + udp_push(&data, sizeof(data)); + udp_push(&ticker, sizeof(ticker)); + + for (i = 0; i < 7; ++i) { + if (i == 3) { + dataptr[1] = Wire.read(); + dataptr[0] = Wire.read(); + udp_push(&data, sizeof(data)); + } else { + discard(Wire.read()); + } + } + data = analogRead(analog); + udp_push(&data, sizeof(data)); + + if (!(udp_flush())) { + Udp.stop(); + sleep(); + } + + blink_led(iled, 20, 80); + ++ticker; +} + +static void sleep(void) +{ + do { + blink_led(iled, 3000, 3000); + } while (1); +} + +static void udp_init_packet(IPAddress ip, const int port) +{ + Udp.beginPacket(ip, port); + memset(udppacketbuffer, 0, sizeof(udppacketbuffer)); + udppacketcursor = udppacketbuffer; +} + +static void udp_push(const void * const data, const size_t size) +{ + memcpy(udppacketcursor, data, size); + udppacketcursor += size; +} + +static int udp_flush(void) +{ + Udp.write((const uint8_t *) udppacketbuffer, udppacketcursor - udppacketbuffer); + return Udp.endPacket(); +} + +static void mpu_wakeup(const int i2caddr) +{ + Wire.beginTransmission(i2caddr); + Wire.write(0x6b); + Wire.write(0); + Wire.endTransmission(1); +} + +static void wifi_connect(const char * const ssid, const char * const password, const char doblink, const int ledpin) +{ + WiFi.begin(ssid, password); + + do { + if (doblink) { + blink_led(ledpin, 250, 250); + } else { + delay (500); + } + } while (WiFi.status() != WL_CONNECTED); +} + +static void blink_led(const int pin, const int ontime, const int offtime) +{ + digitalWrite(pin, HIGH); + delay(ontime); + digitalWrite(pin, LOW); + delay(offtime); +} + +static void discover_client(void) +{ + IPAddress bcastip(255, 255, 255, 255); + static const char servermagic[] = "I love coffee!"; + static const char clientmagic[] = "I love tea!"; + char buffer[32] = {0}; + size_t done = 0; + + do { + udp_init_packet(bcastip, port); + udp_push(servermagic, sizeof(servermagic)); + udp_flush(); + delay(5); + while (Udp.parsePacket()) { + if (Udp.available() >= sizeof(clientmagic)) { + Udp.read(buffer, sizeof(clientmagic)); + if (!(strcmp(clientmagic, buffer))) { + ip = Udp.remoteIP(); + ++done; + } + } + } + delay(95); + } while (!done); +} + +static void discard(int a) +{ + return; +} |