a sensor hub for monitoring home environment
Dependencies: HTS221 LIS3MDL LPS22HB LSM303AGR LSM6DSL VL53L0X picojson
Fork of HelloWorld_ST_Sensors by
main.cpp
- Committer:
- jaafaryn
- Date:
- 2017-12-12
- Revision:
- 11:1e0b9a529ee0
- Parent:
- 8:39ecd15538f9
- Child:
- 12:058b012dbebe
File content as of revision 11:1e0b9a529ee0:
/*------------------------------------------------------------------------------ Home Environment Monitoring with STM32 Discovery IOT Node Disco_HomeEnv Features: - Monitor temperature, relative humidity and air pressure - Connects to a local TSDB server (over http) to log this data - Display the data on a Nextion smart display with 30s autosleep and proximity or touch detection wake up Next: - add RTC sync and time display - add light sensor to monitor illuminance - improve reading by either: reduce power on time of WiFi module (batch logging) or by compensating for board own temperature - add option to choose location from a list and update location tag - incrementally convert the project to electric energy monitoring: - read 2x simultaneous adc channels using DMA - save daily power readings to QSP mem for batch logging and recovey? - add screen to display current power drawing, daily and monthly cumulatives ------------------------------------------------------------------------------*/ #include "main.h" /* ---------- SETUP ------------- */ void setup() { printf("\n***************************************************************\n"); printf("*** Home Env on STM32 IoT Discovery ***\n"); printf("***************************************************************\n"); printf("> Initializing sensors and WiFi... \n"); int range_status; /* Init all sensors with default params */ hum_temp.init(NULL); press_temp.init(NULL); magnetometer.init(NULL); acc_gyro.init(NULL); range_status = range.init_sensor(VL53L0X_DEFAULT_ADDRESS); /* Enable all sensors */ hum_temp.enable(); press_temp.enable(); acc_gyro.enable_x(); acc_gyro.enable_g(); uint8_t id; hum_temp.read_id(&id); printf("HTS221 humidity & temperature id = 0x%X\r\n", id); press_temp.read_id(&id); printf("LPS22HB pressure & temperature id = 0x%X\r\n", id); magnetometer.read_id(&id); printf("LIS3MDL magnetometer id = 0x%X\r\n", id); acc_gyro.read_id(&id); printf("LSM6DSL accelerometer&gyroscope id = 0x%X\r\n", id); printf("VL53L0x status = %d \r\n", range_status); sense_enabled = true; /* Setup display */ WIFI_ICON_OFF; UPLOAD_ICON_OFF; nextion.printf("usup=0\xff\xff\xff");// no wakeup on serial in nextion.printf("thsp=30\xff\xff\xff");// sleep after 30sec no touch nextion.printf("thup=1\xff\xff\xff");// wake up on touch /*Initialize WIFI module */ WiFi_on = connectWiFi(); if (WiFi_on) { led3 = 1; WIFI_ICON_ON; //WiFi_led_ticker.attach(&toggle_led3_cb, 0.25); // sync_time(); } // start event tickers getMeasurementsTicker.attach(&time_to_sense_cb, SENSE_PERIOD_S); sendMeasurementsTicker.attach(&time_to_send_cb, UPLOAD_PERIOD_S); checkProximityTicker.attach(&time_to_check_distance_cb, CHECK_PROXIMITY_PERIOD_S); } // Setup /* ---------- LOOP ------------- */ void loop() { if (take_measurements) { // Environment data hum_temp.get_temperature(&tempC_val); tempF_val = tempC_val*(9.0/5.0) + 32; hum_temp.get_humidity(&RH_val); press_temp.get_pressure(&Patm_val); press_temp.get_temperature(&tempC_val2); // Inertial data /* magnetometer.get_m_axes(axes); printf("LIS3MDL [mag/mgauss]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); acc_gyro.get_x_axes(axes); printf("LSM6DSL [acc/mg]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); acc_gyro.get_g_axes(axes); printf("LSM6DSL [gyro/mdps]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]); */ // print results to terminal /* printf("HTS221: temp= %.2f C, hum= %.2f%%\r\n", tempC_val, RH_val); printf(" temp= %.2f F\n", tempF_val); printf("LPS22HB: patm= %.2f mbar, temp= %.2f C\r\n", Patm_val, tempC_val2); printf("VL53L0X [mm] = %6ld\r\n", distance); */ // refresh screen with updated measurements nextion.printf("valC.txt=\"%.1f\"\xff\xff\xff", tempC_val); nextion.printf("valF.txt=\"%.1f\"\xff\xff\xff", tempF_val); nextion.printf("valRH.txt=\"%.1f\"\xff\xff\xff", RH_val); nextion.printf("valAtm.val=%.0f\xff\xff\xff", Patm_val); nextion.printf("valRange.val=%d\xff\xff\xff", distance); take_measurements = false; }// take measurements if (send_measurements) { //printf("HTS221: temp= %.2f C, hum= %.2f%%\r\n", tempC_val, RH_val); // body of the request char request_body[256]; sprintf(request_body, "disco_iot,loc=%s temperature=%.2f,humidity=%.1f,pressure=%.1f \n","playroom", tempC_val, RH_val, Patm_val); // build header of the request sprintf((char *)http_request, "POST %s HTTP/1.1\r\nHost: %s \r\n", influx_query, InfluxServerUrl); strcat((char *)http_request, "Accept: */*\r\n"); strcat((char *)http_request, "User-agent: ES-WIFI TcpClient\r\n"); strcat((char *)http_request, "Connection: Close\r\n"); //"Connection: Keep-Alive\r\n" char buffer[64]; sprintf(buffer, "Content-Length: %d \r\n\r\n", strlen(request_body)); strcat((char *)http_request, buffer); // append body to the header of the request strcat((char *)http_request, request_body); reqLen = strlen((char *)http_request); // Establish a connection to DB server uint8_t socketid = 1; if (checkWiFi()) { led3 = 1; WIFI_ICON_ON; if (connectToServer(InfluxServerUrl, InfluxServerPort, socketid)) { ledhttp =1; // submit POST request printf("> Sending a POST request with length=%d including a body length=%d\n", reqLen, strlen(request_body)); printf((char *)http_request); uint16_t dataLen; if (WIFI_SendData(socketid, http_request, reqLen, &dataLen, WIFI_WRITE_TIMEOUT) != WIFI_STATUS_OK) { printf("> ERROR: Could not send request to %s", InfluxServerUrl); UPLOAD_ICON_OFF; } else { request_sent++; UPLOAD_ICON_ON; } // get server response // memset(&http_resp[0], 0, sizeof(http_resp)); WIFI_ReceiveData(socketid, http_resp, sizeof(http_resp), &dataLen, WIFI_READ_TIMEOUT); if(dataLen > 0) { /* printf("> Server response:\n"); printf((char *)http_resp); printf("\n> Response length: %d \n", dataLen); */ memset(&buffer[0], 0, sizeof(buffer)); // get the first line of the response strcpy(buffer, strtok((char *)http_resp, "\r\n")); // extract the response code int response_code = 0; sscanf(buffer, "HTTP/1.1 %d", &response_code); printf("> Response code: %d \n", response_code); /* c ommon response codes from InfluxDB API: HTTP/1.1 204 No Content HTTP/1.1 400 Bad Request HTTP/1.1 404 Not Found HTTP/1.1 500 Internal Server Error */ if (response_code == 204) request_acked++; } else { UPLOAD_ICON_OFF; printf("> Error: No response from the server %s.\n", InfluxServerUrl); } printf("> Requests sent: %d, ack'ed: %d\n", request_sent, request_acked); ledhttp = 0; WIFI_CloseClientConnection(socketid); } else { printf("> ERROR: Could not connect to %s \n", InfluxServerUrl); } } else { printf("> ERROR: Could not connect to WiFi \n"); led3 = 0; WIFI_ICON_OFF; } send_measurements = false; } // sendMeasurement() if (check_proximity) { // make sure display is awake when somebody get close to the screen // Proximity value uint32_t dist_val = 0; int status = range.get_distance(&dist_val); if (status == VL53L0X_ERROR_NONE) { distance = (int)dist_val; } else { distance = -1; } if (distance < 400) { nextion.printf("sleep=0\xff\xff\xff");// send wake up command } check_proximity = false; } // check proximity } // Loop int main() { setup(); while(1) { loop(); } } /* */ /* Interrupts servicing callback functions */ /* */ // ISR for flashing WiFi LED /* void toggle_led3_cb() { led3 = !led3; }*/ // ISR to enable taking measurements (and refresh display) void time_to_sense_cb(void) { if (sense_enabled) { take_measurements = true; } } // ISR to enable handling sending data void time_to_send_cb(void) { if (sense_enabled) { send_measurements = true; } } // ISR to enable checking distance void time_to_check_distance_cb(void) { check_proximity = true; } /** * @brief Connect to the WiFi network with credentials in mbed_app.json * @param None * @retval True for WiFi connected, False if there was an error */ bool connectWiFi(void) { uint8_t IP_Addr[4]; uint8_t MAC_Addr[6]; if(WIFI_Init() == WIFI_STATUS_OK) { // printf("> WiFi module initialized.\n"); //if(WIFI_GetModuleName(moduleName) == WIFI_STATUS_OK) { // printf("> Module name: %s\n", moduleName); //} if(WIFI_GetMAC_Address(MAC_Addr) == WIFI_STATUS_OK) { printf("> WiFi module MAC Address : %X:%X:%X:%X:%X:%X\n", MAC_Addr[0], MAC_Addr[1], MAC_Addr[2], MAC_Addr[3], MAC_Addr[4], MAC_Addr[5]); } else { printf("> ERROR : CANNOT get MAC address\n"); } if( WIFI_Connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, WIFI_ECN_WPA2_PSK) == WIFI_STATUS_OK) { // printf("> WiFi connected \n"); if(WIFI_GetIP_Address(IP_Addr) == WIFI_STATUS_OK) { printf("> IP Address : %d.%d.%d.%d\n", IP_Addr[0], IP_Addr[1], IP_Addr[2], IP_Addr[3]); return true; } else { printf("> ERROR : es-wifi module CANNOT get IP address\n"); } } else { printf("> ERROR : es-wifi module NOT connected\n"); } } else { printf("> ERROR : WIFI Module cannot be initialized.\n"); } return false; } /** * @brief check WiFi connection status, retry once if it's offline * @param None * @retval True for WiFi (re)connected, False if reconnection failed */ bool checkWiFi(void) { uint8_t ip_addr[4]; if(WIFI_GetIP_Address(ip_addr) == WIFI_STATUS_OK) return true; else { return connectWiFi(); } } /** * @brief create a TCP session on a server * @param serverUrl : TCP server URL * @param serverPort : port TCP server is listening on * @retval true if connection established */ bool connectToServer(char *serverUrl, uint16_t serverPort, uint8_t socket_id) { uint8_t serverIP[] = {0, 0, 0, 0}; uint16_t trials = CONNECTION_TRIAL_MAX; while (trials--) { // get the server IP through a (local) DNS resolve if (WIFI_GetHostAddress(serverUrl, serverIP) == WIFI_STATUS_OK) { printf("> %s resolved to: %d.%d.%d.%d\n", serverUrl, serverIP[0], serverIP[1], serverIP[2], serverIP[3]); // establish TCP connection to server if( WIFI_OpenClientConnection(socket_id, WIFI_TCP_PROTOCOL, "InfluxDB", serverIP, serverPort, 0) == WIFI_STATUS_OK) { printf("> Connected to %s .\n", serverUrl); return true; } } else { printf("> ERROR : Cannot resolve URL: %s\n", serverUrl); } } if(!trials) { printf("> ERROR : Cannot establish connection\n"); } return false; }