JuanYi
Published

Foolproof Temperature Checker Amid COVID 19 Pandemic

Check if a person is wearing facemask before checking body temperature & check if premise occupied by too many people

IntermediateShowcase (no instructions)Over 1 day92
Foolproof Temperature Checker Amid COVID 19 Pandemic

Things used in this project

Hardware components

AWS IoT EduKit
Amazon Web Services AWS IoT EduKit
×1
OpenMV Cam H7 Plus
×1
IR Sensor MLX90614
×1
Grove - mini PIR motion sensor
Seeed Grove - mini PIR motion sensor
×1

Software apps and online services

VS Code
Microsoft VS Code
Platformio extension
PlatformIO IDE
PlatformIO IDE
As Microsoft VS Code extension
AWS IoT
Amazon Web Services AWS IoT
Edge Impulse Studio
Edge Impulse Studio
OpenMV OpemMV IDE

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Protoboard & soldering

Story

Read more

Custom parts and enclosures

3D printed case - cover

3D printed case - base

Schematics

Schematic

Code

main

C/C++
Since the code is based on smart thermostat project, no point to upload entire project folder. Upload the modified main.c file in main folder instread.
/*
 * AWS IoT EduKit - Core2 for AWS IoT EduKit
 * main.c
 * 
 * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
/**
 * @file main.c
 * @brief simple MQTT publish, subscribe, and device shadows for use with AWS IoT EduKit reference hardware.
 *
 * This example takes the parameters from the build configuration and establishes a connection to AWS IoT Core over MQTT.
 *
 * Some configuration is required. Visit https://edukit.workshop.aws
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <math.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#include "esp_log.h"

#include "aws_iot_config.h"
#include "aws_iot_log.h"
#include "aws_iot_version.h"
#include "aws_iot_mqtt_client_interface.h"
#include "aws_iot_shadow_interface.h"

#include "core2forAWS.h"

#include "wifi.h"
#include "fft.h"
#include "ui.h"
#include "driver/uart.h"
#include "driver/gpio.h"

static const char *TAG = "MAIN";

#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 400

/* CA Root certificate */
extern const uint8_t aws_root_ca_pem_start[] asm("_binary_aws_root_ca_pem_start");
extern const uint8_t aws_root_ca_pem_end[] asm("_binary_aws_root_ca_pem_end");

/* Default MQTT HOST URL is pulled from the aws_iot_config.h */
char HostAddress[255] = AWS_IOT_MQTT_HOST;

/* Default MQTT port is pulled from the aws_iot_config.h */
uint32_t port = AWS_IOT_MQTT_PORT;

TaskHandle_t led_bar_blink_handle;

static void touch_task(void *pvParameters);

bool startUp = true; // flag to run 1st connection upon startup
char temp_str[200];
bool testDesired_prev = false;

// *** json variable for mqtt ***********************************************************************
bool testReported_Increase = false;
bool testReported_Decrease = false;
bool testDesired = false;

// *** uart with openmv **************************************************************************
static void uart_tx_task(void *arg){
    char enableFlag_to_omv[1];
    while (1) {
        if (startUp == false && testDesired_prev != testDesired) {
            if (testDesired == true ) {
                enableFlag_to_omv[0] = '1';  // to enable openmv, blue led openmv will on    
            } else {
                enableFlag_to_omv[0] = '2';  // to disable openmv, blue led openmv will off
            }
            // size_t message_len = strlen(enableFlag_to_omv);
            Core2ForAWS_Port_C_UART_Send(enableFlag_to_omv, 1);
            ESP_LOGI(TAG, "UART send\t: %s", enableFlag_to_omv);
            testDesired_prev = testDesired;
        }
        //ESP_LOGI(TAG, "testDesired\t: %d", testDesired);
        //ESP_LOGI(TAG, "testDesired_prev\t: %d", testDesired_prev);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}
 
void uart_rx_logic(char status_fr_omv, float bodyTemp_fr_omv){
    if (status_fr_omv == '1') {  // set LED blue blink & text "Measuring"
        vTaskResume(led_bar_blink_handle);
        ESP_LOGI(TAG, "Status is 1.");
        sprintf(temp_str, "MEASURING...");     
        ui_textlabel_add(temp_str);

    } else if (status_fr_omv == '2') { // set LED green or red & text according to result
        vTaskSuspend(led_bar_blink_handle);
        ESP_LOGI(TAG, "Status is 2.");
        if (bodyTemp_fr_omv >=36.0 && bodyTemp_fr_omv < 37.5){  // Set green and IOT
            Core2ForAWS_Sk6812_SetBrightness(40);
            Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_LEFT, 0x00b050);
            Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_RIGHT, 0x00b050);
            Core2ForAWS_Sk6812_Show();
            
            sprintf(temp_str, "%.1f degC\n\nWELCOME", bodyTemp_fr_omv);                 

            // Send increase flag to aws iot
            testReported_Increase = true;
            ESP_LOGI(TAG, "Checker triggered to increase");
        }
        else {  // Set red and exit
            Core2ForAWS_Sk6812_SetBrightness(40);   
            Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_LEFT, 0xbe0000);
            Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_RIGHT, 0xbe0000);
            Core2ForAWS_Sk6812_Show();

            sprintf(temp_str, "%.1f degC\n\nSORRY..", bodyTemp_fr_omv);
        }
        ui_textlabel_add(temp_str);
        vTaskDelay(pdMS_TO_TICKS(3000));
        Core2ForAWS_Sk6812_Clear();
        Core2ForAWS_Sk6812_Show();
        ui_textlabel_add(NULL);
    }
}

static void uart_rx_task(void *arg){    // receive result from openmv
    int rxBytes;

    char uart_fr_omv[4];
    char status_fr_omv = '0';
    char uart_fr_omv_bodyTemp[3];
    int uart_fr_omv_bodyTemp_int;
    float bodyTemp_fr_omv = 0.0;


    uint8_t *data = heap_caps_malloc(UART_RX_BUF_SIZE, MALLOC_CAP_SPIRAM); // Allocate space for message in external RAM
    while (1) {
        rxBytes = Core2ForAWS_Port_C_UART_Receive(data);

        if (rxBytes >0) {
            for(int i=0; i<4; i++) {
                uart_fr_omv[i] = data[i];              // somehow data seems not flushing buffer after read
            }                                          // and it retain old string in the data
            
            status_fr_omv = uart_fr_omv[0];
            uart_fr_omv_bodyTemp[0] = uart_fr_omv[1];   // somehow how to use this silly method to extract correct value
            uart_fr_omv_bodyTemp[1] = uart_fr_omv[2];
            uart_fr_omv_bodyTemp[2] = uart_fr_omv[3];
            ESP_LOGI(TAG, "uart_fr_omv_bodyTemp\t: %s\n", uart_fr_omv_bodyTemp);

            uart_fr_omv_bodyTemp_int = atoi(uart_fr_omv_bodyTemp);
            ESP_LOGI(TAG, "uart_fr_omv_bodyTemp_int\t: %d\n", uart_fr_omv_bodyTemp_int);

            bodyTemp_fr_omv = (float)uart_fr_omv_bodyTemp_int/10;
            ESP_LOGI(TAG, "Final Body Temperature\t: %.1f degC\n", bodyTemp_fr_omv);
            uart_rx_logic(status_fr_omv, bodyTemp_fr_omv);
            uart_fr_omv[0] = 0;
            uart_fr_omv_bodyTemp[0] = 0;
        }
        vTaskDelay(pdMS_TO_TICKS(100)); // Read more frequently than transmit to ensure the messages are not erased from buffer.
    }
    free(data); // Free memory from external RAM
}

// *** blink task **************************************************************************
void sk6812_blink_task(void* pvParameters){
    Core2ForAWS_Sk6812_Clear();
    Core2ForAWS_Sk6812_Show();
    Core2ForAWS_Sk6812_SetBrightness(20);
    while (1) {
        
        Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_LEFT, 0x007acc);
        Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_RIGHT, 0x007acc);
        Core2ForAWS_Sk6812_Show();
        vTaskDelay(pdMS_TO_TICKS(500));
        Core2ForAWS_Sk6812_Clear();
        Core2ForAWS_Sk6812_Show();
        vTaskDelay(pdMS_TO_TICKS(500));      
    }
    vTaskDelete(NULL); // Should never get to here...
}

// *** iot callback handler ***********************************************************************
void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
                                    IoT_Publish_Message_Params *params, void *pData) {
    ESP_LOGI(TAG, "Subscribe callback");
    ESP_LOGI(TAG, "%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, (char *)params->payload);
}

void disconnect_callback_handler(AWS_IoT_Client *pClient, void *data) {
    ESP_LOGW(TAG, "MQTT Disconnect");
    ui_textarea_add("Disconnected from AWS IoT Core...", NULL, 0);

    IoT_Error_t rc = FAILURE;

    if(NULL == pClient) {
        return;
    }

    if(aws_iot_is_autoreconnect_enabled(pClient)) {
        ESP_LOGI(TAG, "Auto Reconnect is enabled, Reconnecting attempt will start now");
    } else {
        ESP_LOGW(TAG, "Auto Reconnect not enabled. Starting manual reconnect...");
        rc = aws_iot_mqtt_attempt_reconnect(pClient);
        if(NETWORK_RECONNECTED == rc) {
            ESP_LOGW(TAG, "Manual Reconnect Successful");
        } else {
            ESP_LOGW(TAG, "Manual Reconnect Failed - %d", rc);
        }
    }
}

static bool shadowUpdateInProgress;

void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
                                const char *pReceivedJsonDocument, void *pContextData) {
    IOT_UNUSED(pThingName);
    IOT_UNUSED(action);
    IOT_UNUSED(pReceivedJsonDocument);
    IOT_UNUSED(pContextData);

    shadowUpdateInProgress = false;

    if(SHADOW_ACK_TIMEOUT == status) {
        ESP_LOGE(TAG, "Update timed out");
    } else if(SHADOW_ACK_REJECTED == status) {
        ESP_LOGE(TAG, "Update rejected");
    } else if(SHADOW_ACK_ACCEPTED == status) {
        ESP_LOGI(TAG, "Update accepted");
    }
}

// *** desired state callback handler ******************************************************************
void test_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) {
    IOT_UNUSED(pJsonString);
    IOT_UNUSED(JsonStringDataLen);

    if(pContext != NULL) {
        ESP_LOGI(TAG, "Delta - testDesired state changed to %d", *(bool *) (pContext->pData));
    }
}

// *** aws iot task ***********************************************************************
void aws_iot_task(void *param) {
    IoT_Error_t rc = FAILURE;

    char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER];
    size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]);
    
    // *** json variable ***********************************************************************
    jsonStruct_t testHandler_Increase;
    testHandler_Increase.cb = NULL;
    testHandler_Increase.pKey = "testReported_Increase";
    testHandler_Increase.pData = &testReported_Increase;
    testHandler_Increase.type = SHADOW_JSON_BOOL;
    testHandler_Increase.dataLength = sizeof(bool);

    jsonStruct_t testHandler_Decrease;
    testHandler_Decrease.cb = NULL;
    testHandler_Decrease.pKey = "testReported_Decrease";
    testHandler_Decrease.pData = &testReported_Decrease;
    testHandler_Decrease.type = SHADOW_JSON_BOOL;
    testHandler_Decrease.dataLength = sizeof(bool);

    jsonStruct_t testActuator;
    testActuator.cb = test_Callback;
    testActuator.pKey = "testDesired";
    testActuator.pData = &testDesired;
    testActuator.type = SHADOW_JSON_BOOL;
    testActuator.dataLength = sizeof(bool);

    ESP_LOGI(TAG, "AWS IoT SDK Version %d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);

    // initialize the mqtt client
    AWS_IoT_Client iotCoreClient;

    ShadowInitParameters_t sp = ShadowInitParametersDefault;
    sp.pHost = HostAddress;
    sp.port = port;
    sp.enableAutoReconnect = false;
    sp.disconnectHandler = disconnect_callback_handler;

    sp.pRootCA = (const char *)aws_root_ca_pem_start;
    sp.pClientCRT = "#";
    sp.pClientKey = "#0";
    
    #define CLIENT_ID_LEN (ATCA_SERIAL_NUM_SIZE * 2)
    char *client_id = malloc(CLIENT_ID_LEN + 1);
    ATCA_STATUS ret = Atecc608_GetSerialString(client_id);
    if (ret != ATCA_SUCCESS){
        ESP_LOGE(TAG, "Failed to get device serial from secure element. Error: %i", ret);
        abort();
    }

    ui_textarea_add("\nDevice client Id:\n>> %s <<\n", client_id, CLIENT_ID_LEN);

    /* Wait for WiFI to show as connected */
    xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
                        false, true, portMAX_DELAY);

    ESP_LOGI(TAG, "Shadow Init");

    rc = aws_iot_shadow_init(&iotCoreClient, &sp);
    if(SUCCESS != rc) {
        ESP_LOGE(TAG, "aws_iot_shadow_init returned error %d, aborting...", rc);
        abort();
    }

    ShadowConnectParameters_t scp = ShadowConnectParametersDefault;
    scp.pMyThingName = client_id;
    scp.pMqttClientId = client_id;
    scp.mqttClientIdLen = CLIENT_ID_LEN;

    ESP_LOGI(TAG, "Shadow Connect");
    rc = aws_iot_shadow_connect(&iotCoreClient, &scp);
    if(SUCCESS != rc) {
        ESP_LOGE(TAG, "aws_iot_shadow_connect returned error %d, aborting...", rc);
        abort();
    }
    ui_wifi_label_update(true); // Switch wifi label to green color
    ui_textarea_add("\nConnected to AWS IoT Core and pub/sub to the device shadow state\n", NULL, 0);

    rc = aws_iot_shadow_set_autoreconnect_status(&iotCoreClient, true);
    if(SUCCESS != rc) {
        ESP_LOGE(TAG, "Unable to set Auto Reconnect to true - %d, aborting...", rc);
        abort();
    }

    // *** register delta callback  ***************************************************************
    rc = aws_iot_shadow_register_delta(&iotCoreClient, &testActuator);
    if(SUCCESS != rc) {
        ESP_LOGE(TAG, "Shadow Register Delta Error");
    }

    // loop and publish changes
    while(NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) {
        rc = aws_iot_shadow_yield(&iotCoreClient, 500);
        if(NETWORK_ATTEMPTING_RECONNECT == rc || shadowUpdateInProgress) {
            rc = aws_iot_shadow_yield(&iotCoreClient, 1000);
            // If the client is attempting to reconnect, or already waiting on a shadow update,
            // we will skip the rest of the loop.
            continue;
        }
        // *** Test ***********************************************************************
        ESP_LOGI(TAG, "Just a trigger to see if connection is alive.....................");

        if (startUp == true || testReported_Increase == true || testReported_Decrease == true){

            ESP_LOGI(TAG, "*****************************************************************************************");
            // *** json variable ***********************************************************************
            ESP_LOGI(TAG, "On Device: testReported_Increase %s", testReported_Increase ? "true" : "false");
            ESP_LOGI(TAG, "On Device: testReported_Decrease %s", testReported_Decrease ? "true" : "false");
            ESP_LOGI(TAG, "On Device: testDesired %s", testDesired ? "true" : "false");

            rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);
            if(SUCCESS == rc) {
               rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 3,
                                                &testHandler_Increase, &testHandler_Decrease, &testActuator);
                if(SUCCESS == rc) {
                    rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);
                    if(SUCCESS == rc) {
                        ESP_LOGI(TAG, "Update Shadow: %s", JsonDocumentBuffer);
                        rc = aws_iot_shadow_update(&iotCoreClient, client_id, JsonDocumentBuffer,
                                                ShadowUpdateStatusCallback, NULL, 6, true);
                        shadowUpdateInProgress = true;
                    }
                }
            }

            ESP_LOGI(TAG, "*****************************************************************************************");
            ESP_LOGI(TAG, "Stack remaining for task '%s' is %d bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL));
            
            
            testReported_Increase = false;
            testReported_Decrease = false;
            if (startUp == true) {
                vTaskDelay(pdMS_TO_TICKS(3000));
                startUp = false;
                sprintf(temp_str, "INITIALIZED.");     
                ui_textlabel_add(temp_str);
            }
        }
        vTaskDelay(pdMS_TO_TICKS(2000));
    }

    if(SUCCESS != rc) {
        ESP_LOGE(TAG, "An error occurred in the loop %d", rc);
    }

    ESP_LOGI(TAG, "Disconnecting");
    rc = aws_iot_shadow_disconnect(&iotCoreClient);

    if(SUCCESS != rc) {
        ESP_LOGE(TAG, "Disconnect error %d", rc);
    }

    vTaskDelete(NULL);
}

// *** touch task for manual trigger test **********************************************************
static void touch_task(void *pvParameters){
    for(;;){
        if(Button_WasReleased(button_left)){
            testReported_Increase = true;
            testReported_Decrease = false;
            ESP_LOGI(TAG, "Button left pressed to increase");
            sprintf(temp_str, "Simulate to INCREASE");     
            ui_textlabel_add(temp_str);
            vTaskDelay(pdMS_TO_TICKS(3000));
            ui_textlabel_add(NULL);

        }
        if(Button_WasReleased(button_right)){
            testReported_Decrease = true;
            testReported_Increase = false;
            ESP_LOGI(TAG, "Button right pressed to decrease");
            sprintf(temp_str, "Simulate to DECREASE");     
            ui_textlabel_add(temp_str);
            vTaskDelay(pdMS_TO_TICKS(3000));
            ui_textlabel_add(NULL);
        }
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

// *** PIR sensor at portB ******************************************************************
void readInputTask(){ 
    bool pir_curr = false;
    bool pir_prev = false;
    int pir_count = 0;
    for(;;){
        pir_curr = Core2ForAWS_Port_Read(GPIO_NUM_26);
        
        if (pir_curr != pir_prev) {
            if (pir_curr == true){
                pir_count++;        // counter to avoid accidental trigger
                if (pir_count > 10){
                    // Send decrease flag to aws iot
                    testReported_Decrease = true;
                    ESP_LOGI(TAG, "PIR sensor triggered!"); 
                    pir_count = 0;
                    pir_prev = pir_curr;
                }
            } else {
                pir_count = 0;
                pir_prev = pir_curr;
            }
        } else{
            pir_count = 0;
        }
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

void app_main()
{   
    ESP_LOGI(TAG, "\n***************************************************\nFoolproof Temperature Checker & Crowd Control\n***************************************************");
    Core2ForAWS_Init();
    Core2ForAWS_Display_SetBrightness(50);

    ui_init();
    initialise_wifi();
    xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", 4096*2, NULL, 5, NULL, 1);
    xTaskCreatePinnedToCore(touch_task, "touch_Task", configMINIMAL_STACK_SIZE * 2, NULL, 1, NULL, 1);

    esp_err_t err = Core2ForAWS_Port_PinMode(PORT_C_UART_TX_PIN, UART);
    if (err == ESP_OK){
        Core2ForAWS_Port_C_UART_Begin(115200);
        xTaskCreate(uart_rx_task, "uart_rx", 1024*3, NULL, configMAX_PRIORITIES, NULL);
        xTaskCreate(uart_tx_task, "uart_tx", 1024*2, NULL, configMAX_PRIORITIES-1, NULL);
    }

    esp_err_t err_GPIO26 = Core2ForAWS_Port_PinMode(GPIO_NUM_26, INPUT);
    if(err_GPIO26 == ESP_OK){
        xTaskCreatePinnedToCore(readInputTask, "read_pin", 1024*4, NULL, 1, NULL, 1);
    }

    xTaskCreatePinnedToCore(sk6812_blink_task, "sk6812BlinkTask", configMINIMAL_STACK_SIZE * 3, NULL, 1, &led_bar_blink_handle, 1);
    vTaskSuspend(led_bar_blink_handle);
}

ui.c

C/C++
Since the code is based on smart thermostat project, no point to upload entire project folder. Upload the modified ui.c file in main folder instead.
/*
 * AWS IoT EduKit - Core2 for AWS IoT EduKit
 * ui.c
 * 
 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"

#include "esp_log.h"
#include "core2forAWS.h"
#include "ui.h"

#define MAX_TEXTAREA_LENGTH 1024

static lv_obj_t *active_screen;
static lv_obj_t *out_txtarea;
static lv_obj_t *wifi_label;

static lv_style_t bg_style;
static lv_obj_t* screen_bg;
static lv_obj_t* temp_label;

static char *TAG = "UI";

TaskHandle_t power_handle;

static void ui_textarea_prune(size_t new_text_length){
    const char * current_text = lv_textarea_get_text(out_txtarea);
    size_t current_text_len = strlen(current_text);
    if(current_text_len + new_text_length >= MAX_TEXTAREA_LENGTH){
        for(int i = 0; i < new_text_length; i++){
            lv_textarea_set_cursor_pos(out_txtarea, 0);
            lv_textarea_del_char_forward(out_txtarea);
        }
        lv_textarea_set_cursor_pos(out_txtarea, LV_TEXTAREA_CURSOR_LAST);
    }
}

void ui_textarea_add(char *baseTxt, char *param, size_t paramLen) {
    if( baseTxt != NULL ){
        xSemaphoreTake(xGuiSemaphore, portMAX_DELAY);
        if (param != NULL && paramLen != 0){
            size_t baseTxtLen = strlen(baseTxt);
            ui_textarea_prune(paramLen);
            size_t bufLen = baseTxtLen + paramLen;
            char buf[(int) bufLen];
            sprintf(buf, baseTxt, param);
            lv_textarea_add_text(out_txtarea, buf);
        } 
        else{
            lv_textarea_add_text(out_txtarea, baseTxt); 
        }
        xSemaphoreGive(xGuiSemaphore);
    } 
    else{
        ESP_LOGE(TAG, "Textarea baseTxt is NULL!");
    }
}

void ui_wifi_label_update(bool state){
    xSemaphoreTake(xGuiSemaphore, portMAX_DELAY);
    if (state == false) {
        lv_label_set_text(wifi_label, LV_SYMBOL_WIFI);
    } 
    else{
        char buffer[25];
        //sprintf (buffer, "#0000ff %s #", LV_SYMBOL_WIFI);
        sprintf (buffer, "#0ab300 %s #", LV_SYMBOL_WIFI);
        lv_label_set_text(wifi_label, buffer);
    }
    xSemaphoreGive(xGuiSemaphore);
}

void ui_textlabel_add(char *baseTxt) {
    xSemaphoreTake(xGuiSemaphore, portMAX_DELAY);
    if( baseTxt != NULL ) {
        lv_label_set_text(temp_label, baseTxt);
        lv_obj_align(temp_label, screen_bg, LV_ALIGN_CENTER, 0, 55);
    } else {
        lv_label_set_text(temp_label, "");
    }
    xSemaphoreGive(xGuiSemaphore);
}

void battery_task(void* pvParameters){
    xSemaphoreTake(xGuiSemaphore, portMAX_DELAY);
    lv_obj_t* battery_label = lv_label_create((lv_obj_t*)pvParameters, NULL);
    lv_label_set_text(battery_label, LV_SYMBOL_BATTERY_FULL);
    lv_label_set_recolor(battery_label, true);
    lv_label_set_align(battery_label, LV_LABEL_ALIGN_CENTER);
    lv_obj_align(battery_label, (lv_obj_t*)pvParameters, LV_ALIGN_IN_TOP_RIGHT,-8, 7);
    lv_obj_t* charge_label = lv_label_create(battery_label, NULL);
    lv_label_set_recolor(charge_label, true);
    lv_label_set_text(charge_label, "");
    lv_obj_align(charge_label, battery_label, LV_ALIGN_CENTER, -4, 1);
    xSemaphoreGive(xGuiSemaphore);

    for(;;){
        xSemaphoreTake(xGuiSemaphore, portMAX_DELAY);
        float battery_voltage = Core2ForAWS_PMU_GetBatVolt();
        if(battery_voltage >= 4.100){
            lv_label_set_text(battery_label, "#0ab300 " LV_SYMBOL_BATTERY_FULL "#");
        } else if(battery_voltage >= 3.95){
            lv_label_set_text(battery_label, "#0ab300 " LV_SYMBOL_BATTERY_3 "#");
        } else if(battery_voltage >= 3.80){
            lv_label_set_text(battery_label, "#ff9900 " LV_SYMBOL_BATTERY_2 "#");
        } else if(battery_voltage >= 3.25){
            lv_label_set_text(battery_label, "#ff0000 " LV_SYMBOL_BATTERY_1 "#");
        } else{
            lv_label_set_text(battery_label, "#ff0000 " LV_SYMBOL_BATTERY_EMPTY "#");
        }

        if(Core2ForAWS_PMU_GetBatCurrent() >= 0.00){
            lv_label_set_text(charge_label, "#0000cc " LV_SYMBOL_CHARGE "#");
        } else{
            lv_label_set_text(charge_label, "");
        }
        xSemaphoreGive(xGuiSemaphore);
        vTaskDelay(pdMS_TO_TICKS(200));
    }

    vTaskDelete(NULL); // Should never get to here...
}

void ui_init() {
    xSemaphoreTake(xGuiSemaphore, portMAX_DELAY);
    active_screen = lv_scr_act();
    wifi_label = lv_label_create(active_screen, NULL);
    lv_obj_align(wifi_label,NULL,LV_ALIGN_IN_TOP_RIGHT, -20, 6);
    lv_label_set_text(wifi_label, LV_SYMBOL_WIFI);
    lv_label_set_recolor(wifi_label, true);

    /* Create the main body object and set background within the tab*/
    screen_bg = lv_obj_create(active_screen, NULL);
    lv_obj_align(screen_bg, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 30);
    lv_obj_set_size(screen_bg, 300, 40);
    lv_obj_set_click(screen_bg, false);
    lv_style_init(&bg_style);
    lv_style_set_bg_color(&bg_style, LV_STATE_DEFAULT, lv_color_make(0, 100, 200));
    lv_obj_add_style(screen_bg, LV_OBJ_PART_MAIN, &bg_style);

    /* Create the title within the main body object */
    static lv_style_t title_style;
    lv_style_init(&title_style);
    lv_style_set_text_font(&title_style, LV_STATE_DEFAULT, LV_THEME_DEFAULT_FONT_TITLE);
    lv_style_set_text_color(&title_style, LV_STATE_DEFAULT, LV_COLOR_WHITE);
    lv_obj_t* tab_title_label = lv_label_create(screen_bg, NULL);
    lv_obj_add_style(tab_title_label, LV_OBJ_PART_MAIN, &title_style);
    lv_label_set_static_text(tab_title_label, "Foolproof Temperature Checker");
    lv_obj_align(tab_title_label, screen_bg, LV_ALIGN_IN_TOP_MID, 0, 10);

    temp_label = lv_label_create(active_screen, NULL);
    // lv_obj_align(temp_label, screen_bg, LV_ALIGN_IN_TOP_MID, -100, 50);
    static lv_style_t temp_style;
    lv_style_init(&temp_style);
    lv_style_set_text_font(&temp_style, LV_STATE_DEFAULT, LV_THEME_DEFAULT_FONT_TITLE);
    lv_style_set_text_color(&temp_style, LV_STATE_DEFAULT, LV_COLOR_BLACK);
    lv_obj_add_style(temp_label, LV_OBJ_PART_MAIN, &temp_style);
    lv_label_set_text(temp_label, "INITIALIZING...");
    lv_label_set_align(temp_label, LV_LABEL_ALIGN_CENTER);
    lv_obj_align(temp_label, screen_bg, LV_ALIGN_CENTER, 0, 55);

    out_txtarea = lv_textarea_create(active_screen, NULL);
    lv_obj_set_size(out_txtarea, 300, 80);
    lv_obj_align(out_txtarea, NULL, LV_ALIGN_IN_TOP_MID, 0, 150);
    lv_obj_set_click(out_txtarea, false);
    lv_textarea_set_max_length(out_txtarea, MAX_TEXTAREA_LENGTH);
    lv_textarea_set_text_sel(out_txtarea, false);
    lv_textarea_set_cursor_hidden(out_txtarea, true);
    lv_textarea_set_text(out_txtarea, "");

    xSemaphoreGive(xGuiSemaphore);

    xTaskCreatePinnedToCore(battery_task, "batteryTask", configMINIMAL_STACK_SIZE * 2, (void*) active_screen, 0, &power_handle, 1);
}

wifi.c

C/C++
Since the code is based on smart thermostat project, no point to upload entire project folder. Upload the modified wifi.c file in main folder instead.
/*
 * AWS IoT EduKit - Core2 for AWS IoT EduKit
 * wifi.c
 * 
 * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

#include <string.h>

#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "wifi.h"
#include "ui.h"

static const char *TAG = "WIFI";

static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data){
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        wifi_event_sta_disconnected_t* event = (wifi_event_sta_disconnected_t*) event_data;
        ESP_LOGE(TAG, "Wi-Fi disconnected. Reason: %d\n", event->reason);
        ESP_LOGI(TAG, "Wi-Fi reason codes: https://docs.espressif.com/projects/esp-idf/en/v4.2/esp32/api-guides/wifi.html#wi-fi-reason-code");
        ui_textarea_add("WiFi error. Attempting reconnect...\n", NULL, 0);
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
        xEventGroupSetBits(wifi_event_group, DISCONNECTED_BIT);
        ui_wifi_label_update(false);
        esp_wifi_connect();
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "Device IP address: " IPSTR, IP2STR(&event->ip_info.ip));
        xEventGroupClearBits(wifi_event_group, DISCONNECTED_BIT);
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
        //ui_wifi_label_update(true);
    }
}

void initialise_wifi(void){
    // Initialize NVS
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK(err);

    wifi_event_group = xEventGroupCreate();
    
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL));

    // Initialize default station as network interface instance (esp-netif)
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);
    
    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = CONFIG_WIFI_SSID,
            .password = CONFIG_WIFI_PASSWORD,
        },
    };
    ESP_LOGI(TAG, "Setting Wi-Fi configuration to SSID: %s", wifi_config.sta.ssid);
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());
}

Foolproof Temp Checker R5_20211007.py

MicroPython
Code for OpenMV H7 Plus to run image classification for mask detection and read temperature from MLX90614
# Title: Foolproof temperature checker
# Description: OpenMV run inference check if mask detected then start
#              temperature measurement using MLX90614
#              & display result on the lcd shield --> removed
#              & communicate with core2 --> added
# Connection:
#   MLX90614  OpenMV    Core2
#   VCC       VCC
#   GND       GND
#   SCL       SCL
#   SDA       SDA
#             VIN       PortC.5V
#             GND       PortC.GND
#             P0.RX     PortC.TX
#             P1.TX     PortC.RX
#
# R1 - Initial release for testing
# R2 - Flow:
#       Check MaskYes for consecutive 5 frames
#       If yes, check temp if above 36degC
#       Average those temp above 36degC
#       Display result at LCD for 3sec. --> removed
#       Add led to lit according to the status (green led not working)
# R3 - Add LED toggle
# R4 - Remove lcd part
#      Add uart for comm to core2. Design:
#       bit 0:      int status_to_core2,
#       bit 123:    int bodyTemp_to_core2
#      Change led trigger timing and condition
#      Change check_temp logic to also calculate
#       tAvg when tObj below 36degC, to show number at least
# R5 - Add null terminator to uart string

from pyb import I2C, LED, UART
import sensor, image, time, os, tf, lcd, micropython, pyb

micropython.alloc_emergency_exception_buf(100)

# LED flash ----------------------------------------------------------------------------------------
class Foo(object):
    def __init__(self, timer, led):
        self.led = led
        self.timer = timer
        timer.callback(self.cb)
    def cb(self, tim):
        self.led.toggle()
    def deinit(self):
        self.timer.deinit()

# LED selection ------------------------------------------------------------------------------------
def light(r, g, b):
    if r == True:
        red_led.on()
    else:
        red_led.off()
    if g == True:
        green_led.on()
    else:
        green_led.off()
    if b == True:
        blue_led.on()
    else:
        blue_led.off()

# Temperature function------------------------------------------------------------------------------
def check_temp():   # To take only measurement above 36degC into rolling average of ~4s

    global temp_count
    global tAvg
    global tSum
    global avg_count

    global low_tAvg
    global low_tSum
    global low_count

    done = False

    if (temp_count < max_count):
        temp_count += 1
        tObj = ir.getObjCelsius()

        if tObj > 36.0:
            avg_count += 1
            tSum = tSum + tObj
            tAvg = round(tSum/avg_count, 1)
            print("HI_cnt: %d   tObj: %s *C   tSum: %s *C   tAvg: %s *C" % (avg_count, tObj, tSum, tAvg))
        else:
            low_count +=1
            low_tSum = low_tSum + tObj
            low_tAvg = round(low_tSum/low_count, 1)
            print("LOW_cnt: %d   tObj: %s *C   tSum: %s *C   tAvg: %s *C" % (low_count, tObj, low_tSum, low_tAvg))


        if (temp_count == max_count):
            if (avg_count < 1):
                tAvg = low_tAvg
            uart_result = "2" + str(int(tAvg * 10)) + "\0"
            uart.write(uart_result)
            print("UART to Core2: %s" % uart_result)
            temp_count = 0
            avg_count = 0
            tObj = 0.0
            tSum = 0.0

            low_count = 0
            low_tObj = 0.0
            low_tSum = 0.0

            done = True
    return done

# MLX90614 setup -----------------------------------------------------------------------------------
_MLX90614_IIC_ADDR   = (0x5A)
_MLX90614_TA         = (0x06)
_MLX90614_TOBJ1      = (0x07)

class MLX90614:
  def __init__(self,i2c,addr=_MLX90614_IIC_ADDR):
    self.addr=addr
    self.i2c=i2c

  def getObjCelsius(self):
    return self.getTemp(_MLX90614_TOBJ1) + 3	#Get celsius temperature of the object

  def getEnvCelsius(self):
    return self.getTemp(_MLX90614_TA) + 1   #Get celsius temperature of the ambient

  def getTemp(self,reg):
    temp = self.getReg(reg)*0.02-273.15             #Temperature conversion
    return temp

  def getReg(self,reg):
    data = self.i2c.mem_read(3,self.addr,reg)               #Receive DATA
    result = (data[1]<<8) | data[0]
    return result

# I2C setup ----------------------------------------------------------------------------------------
i2c = I2C(2,I2C.MASTER,baudrate=100000)
ir = MLX90614(i2c)

# Set uart settings --------------------------------------------------------------------------------
uart = UART(1, 115200, timeout_char=1000)       #UART 1 RX -> P0; TX -> P1
uart.init(115200, bits=8, parity=None, stop=1)

# LED setup ----------------------------------------------------------------------------------------
red_led   = LED(1)
green_led = LED(2)
blue_led  = LED(3)

# Sensor setup -------------------------------------------------------------------------------------
sensor.reset()                         # Reset and initialize the sensor.
sensor.set_pixformat(sensor.RGB565)    # Set pixel format to RGB565 (or GRAYSCALE)
sensor.set_framesize(sensor.VGA)       # Set frame size to QVGA (320x240)
sensor.set_windowing((360, 360))       # Set 240x240 window.
sensor.skip_frames(time=2000)          # Let the camera adjust.

# tensorflow lite setup ----------------------------------------------------------------------------
net = "trained.tflite"
labels = [line.rstrip('\n') for line in open("labels.txt")]

# --------------------------------------------------------------------------------------------------
detected = ""
temp_count = 0
avg_count = 0
max_count = 12      # if 4fps then 6count is ~3sec.
detected_count = 0

tObj = 0.0
tAvg = 0.0
tSum = 0.0

low_count = 0
low_tAvg = 0.0
low_tSum = 0.0

clock = time.clock()
isStart = False

isEnd = False
isEnd_count = 0
isEnd_count_max = 16
enableFlag_fr_core2 = '0'
line = ""

while(True):
    clock.tick()

    # ---------------------------------
    if uart.any():
        buf = uart.read()

        if (buf!= '\n'):
            line += str(buf)
        else:
            break
        print(line)
        enableFlag_fr_core2 = line[2]
        print(enableFlag_fr_core2)
        line = ""

    # If enable flag received from core2
    if(enableFlag_fr_core2 == '1'):
        light(False, False, True)
        img = sensor.snapshot().replace(vflip=True, hmirror=True)

        for obj in tf.classify(net, img, min_scale=1.0, scale_mul=0.8, x_overlap=0.5, y_overlap=0.5):
            label_list = list(labels)
            score_list = list(obj.output())
            max_num = max(score_list)
            max_ind = score_list.index(max_num)

            detected = label_list[max_ind]

            # To confirm if really MaskYes detected for continuous 5fps (~1.5sec)
            if isStart == False and isEnd == False:
                if detected == "MaskYes":
                    if detected_count < 5:
                        detected_count +=1
                        print("Detected MaskYes count : %d" % detected_count)
                        img.draw_string(125, 30, detected , color = (100, 250, 250), scale = 5, mono_space = False)
                        img.draw_rectangle(116, 116, 128, 128, color=(100, 250, 100), thickness=1)
                        img.replace(vflip=True, hmirror=True)
                        light(False, False, True)

                        if detected_count == 5:
                            isStart = True
                            uart.write("1000\n")
                            print("UART to Core2: 1")
                            light(False, False, False)
                            blueFlash = Foo(pyb.Timer(4, freq=4), blue_led)

                else:
                    detected_count = 0
                    print("Detected object is %s" % detected)
                    img.draw_string(125, 30, detected , color = (100, 250, 250), scale = 5, mono_space = False)
                    img.replace(vflip=True, hmirror=True)

            # Once confirm "MaskYes", start to take measurement
            elif isStart == True and isEnd == False :
                print("Measuring...")
                img.draw_string(115, 150, "Measuring..." , color = (100, 250, 250), scale = 3, mono_space = False)
                img.draw_rectangle(116, 116, 128, 128, color=(100, 250, 100), thickness=5)
                img.replace(vflip=True, hmirror=True)

                if check_temp() == True:
                    isStart = False
                    isEnd = True

            # Once done measurement, display it in frame buffer
            elif isStart == False and isEnd == True:
                if isEnd_count < isEnd_count_max:
                    isStart = False
                    isEnd_count += 1
                    print("%d: Final temperature : %s *C" % (isEnd_count, tAvg))
                    img.draw_string(130, 150, str(tAvg) , color = (100, 250, 250), scale = 5, mono_space = False)
                    img.draw_rectangle(116, 116, 128, 128, color=(100, 250, 100), thickness=5)
                    img.replace(vflip=True, hmirror=True)
                    blueFlash.deinit()
                    light(False, False, True)
                else:
                    isEnd = False
                    isEnd_count = 0
                    tAvg = 0.0
                    light(False, False, True)

            print(clock.fps(), "fps")

    else:
        light(False, False, False)
        time.sleep_ms(1000)

trained.tflite

C/C++
Generated firmware by EDGE IMPULSE for running MobileNetV2 model in OpenMV H7 Plus
No preview (download only).

labels.txt

XML
Label text for MobileNetV2 in OpenMV H7 Plus
Hand
MaskNo
MaskYes

AWS IoT Event Detector Model

JSON
{
    "detectorModelDefinition": {
        "states": [
            {
                "stateName": "Enabled_State",
                "onInput": {
                    "events": [],
                    "transitionEvents": [
                        {
                            "eventName": "Enabled",
                            "condition": "true",
                            "actions": [],
                            "nextState": "Counting"
                        }
                    ]
                },
                "onEnter": {
                    "events": [
                        {
                            "eventName": "testDesired_true",
                            "condition": "true",
                            "actions": [
                                {
                                    "iotTopicPublish": {
                                        "mqttTopic": "$aws/things/<YOURID>/shadow/update",
                                        "payload": {
                                            "contentExpression": "'{ \"state\": { \"desired\": { \"testDesired\": true} } }'",
                                            "type": "JSON"
                                        }
                                    }
                                },
                                {
                                    "setVariable": {
                                        "variableName": "testDesired_state",
                                        "value": "true"
                                    }
                                }
                            ]
                        },
                        {
                            "eventName": "enabled_prev1",
                            "condition": "true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "enabled_prev",
                                        "value": "true"
                                    }
                                }
                            ]
                        },
                        {
                            "eventName": "disabled_prev0",
                            "condition": "true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "disabled_prev",
                                        "value": "false"
                                    }
                                }
                            ]
                        }
                    ]
                },
                "onExit": {
                    "events": []
                }
            },
            {
                "stateName": "Counting",
                "onInput": {
                    "events": [
                        {
                            "eventName": "testReported_Increase",
                            "condition": "$input.testInput.current.state.reported.testReported_Increase == true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "testReported_count",
                                        "value": "$variable.testReported_count + 1"
                                    }
                                }
                            ]
                        },
                        {
                            "eventName": "testReported_Decrease",
                            "condition": "$input.testInput.current.state.reported.testReported_Decrease == true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "testReported_count",
                                        "value": "$variable.testReported_count - 1"
                                    }
                                }
                            ]
                        }
                    ],
                    "transitionEvents": [
                        {
                            "eventName": "Disabling",
                            "condition": "($variable.testReported_count >= $variable.countThreshold) && ($variable.disabled_prev != true)",
                            "actions": [],
                            "nextState": "Disabled_State"
                        },
                        {
                            "eventName": "Enabling",
                            "condition": "($variable.testReported_count < $variable.countThreshold) && ($variable.enabled_prev != true)",
                            "actions": [],
                            "nextState": "Enabled_State"
                        }
                    ]
                },
                "onEnter": {
                    "events": [
                        {
                            "eventName": "varFirstRun",
                            "condition": "$variable.varFirstRun != true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "varFirstRun",
                                        "value": "false"
                                    }
                                }
                            ]
                        },
                        {
                            "eventName": "testReported_count",
                            "condition": "$variable.varFirstRun != true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "testReported_count",
                                        "value": "0"
                                    }
                                }
                            ]
                        },
                        {
                            "eventName": "setThreshold",
                            "condition": "$variable.varFirstRun != true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "countThreshold",
                                        "value": "5"
                                    }
                                }
                            ]
                        },
                        {
                            "eventName": "testDesired_state",
                            "condition": "$variable.varFirstRun != true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "testDesired_state",
                                        "value": "false"
                                    }
                                }
                            ]
                        },
                        {
                            "eventName": "enabled_prev",
                            "condition": "$variable.varFirstRun != true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "enabled_prev",
                                        "value": "false"
                                    }
                                }
                            ]
                        },
                        {
                            "eventName": "disabled_prev",
                            "condition": "$variable.varFirstRun != true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "disabled_prev",
                                        "value": "false"
                                    }
                                }
                            ]
                        }
                    ]
                },
                "onExit": {
                    "events": [
                        {
                            "eventName": "varFirstRun_true",
                            "condition": "true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "varFirstRun",
                                        "value": "true"
                                    }
                                }
                            ]
                        }
                    ]
                }
            },
            {
                "stateName": "Disabled_State",
                "onInput": {
                    "events": [],
                    "transitionEvents": [
                        {
                            "eventName": "Disabled",
                            "condition": "true",
                            "actions": [],
                            "nextState": "Counting"
                        }
                    ]
                },
                "onEnter": {
                    "events": [
                        {
                            "eventName": "testDesired_false",
                            "condition": "true",
                            "actions": [
                                {
                                    "iotTopicPublish": {
                                        "mqttTopic": "$aws/things/<YOURID>/shadow/update",
                                        "payload": {
                                            "contentExpression": "'{ \"state\": { \"desired\": { \"testDesired\": false } } }'",
                                            "type": "JSON"
                                        }
                                    }
                                },
                                {
                                    "setVariable": {
                                        "variableName": "testDesired_state",
                                        "value": "false"
                                    }
                                }
                            ]
                        },
                        {
                            "eventName": "disabled_prev1",
                            "condition": "true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "disabled_prev",
                                        "value": "true"
                                    }
                                }
                            ]
                        },
                        {
                            "eventName": "enabled_prev0",
                            "condition": "true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "enabled_prev",
                                        "value": "false"
                                    }
                                }
                            ]
                        }
                    ]
                },
                "onExit": {
                    "events": []
                }
            }
        ],
        "initialStateName": "Counting"
    },
    "detectorModelDescription": null,
    "detectorModelName": "testModel",
    "evaluationMethod": "SERIAL",
    "key": null,
    "roleArn": "arn:aws:iam::503830644201:role/service-role/Test2"
}

input.json

JSON
Since the code is based on smart thermostat project, no point to upload entire project folder. Upload the modified input.json in project root folder.
{
  "current": {
    "state": {
      "reported": {
        "testReported_Increase": false,
        "testReported_Deccrease": false,
        "testDesired": false
      }
    },
    "version": 13
  },
  "timestamp": 1606282489
}

Credits

JuanYi

JuanYi

2 projects • 2 followers

Comments

Add projectSign up / Login