Embedded System Project for Group 9 Wearable Infant Growth Monitoring

Dependencies:   SX1276 Sht31 C12832

main.cpp

Committer:
akramaliomar
Date:
2021-07-12
Revision:
3:e441033734d3
Parent:
0:bcf3192451ab

File content as of revision 3:e441033734d3:

#include "mbed.h"
#include "C12832.h"
#include "Sht31.h"
#include <string>
#include <time.h>
#include "mbed_trace.h"
#include "mbed_events.h"
#include "LoRaWANInterface.h"
#include "SX1276_LoRaRadio.h"


// Device credentials, register device as OTAA in The Things Network and copy credentials here
static uint8_t DEV_EUI[] = { 0x13, 0x15, 0x17, 0x19, 0x23, 0x25, 0x27, 0x29 };
static uint8_t APP_EUI[] = { 0x13, 0x15, 0x17, 0x19, 0x23, 0x25, 0x27, 0x29 };
static uint8_t APP_KEY[] = { 0x86, 0xD9, 0x65, 0x1C, 0x29, 0x05, 0x78, 0xCF, 0x7E, 0x44, 0x2E, 0x63, 0x13, 0xAB, 0x51, 0x93 };

// The port we're sending and receiving on
#define MBED_CONF_LORA_APP_PORT     15

// Peripherals (LoRa radio, temperature sensor and button)
SX1276_LoRaRadio radio(D11, D12, D13, D10, A0, D2, D3, D4, D5, D8, D9, NC, NC, NC, NC, A4, NC, NC);
//Sht31 sht31(I2C_SDA, I2C_SCL);
DigitalOut led(LED1);
// EventQueue is required to dispatch events around
static EventQueue ev_queue;

// Constructing Mbed LoRaWANInterface and passing it down the radio object.
static LoRaWANInterface lorawan(radio);

// Application specific callbacks
static lorawan_app_callbacks_t callbacks;

// LoRaWAN stack event handler
static void lora_event_handler(lorawan_event_t event);


C12832 lcd(SPI_MOSI, SPI_SCK, SPI_MISO, p8, p11);
Sht31 sht31(I2C_SDA, I2C_SCL);
DigitalOut whiteLed(p10);
DigitalOut blueLed(p11);
DigitalOut redLed(p9);
InterruptIn directionBtn(p20);
InterruptIn modeSwith(p14);
Timeout t,t2;
EventQueue queue;
int scrollingState=0;
int currentTopic=0;
int currentIndex=0;
int scrolling=1;
bool direction = false;
Ticker ticker, ticker2, ticker3, ticker4;
int hold3=0;
int hold5=0;
int holdDuration=0;
time_t rawtime, rawtime1, rawreadtime1;
int starttime=0;
int duration=0;
int starreadttime=0;
char birth[25]="Sun May 02 00:00:00 2021";
int readingDuration=0;
string topic[5][5] = {
    {
    "1- Fulfill Increased Feeding Requirements",
    "2- Identify And Take Care Of Sleeping Times",
    "3- Attend To Your Baby When She Cries",
    "4- Encourage Your Baby’s Development",
    "5- Interact With Her"
    },
    {
    "1- Burping your baby",
    "2- Preventing bug bites",
    "3- Practicing sun safety",
    "4- Not giving honey",
    "5- Bathing"
    },
    {
    "1- A Day in the Life",
    "2- Baby Care Basics",
    "3- Feeding & Nutrition",
    "4- Sleep",
    "5- Health & Safety"
    },
    {
    "1- Walking",
    "2- Speech",
    "3- Teething",
    "4- Identification",
    "5- Sleep"
    }
    
};

string content[5][5] = {
    {
    "11- Try to identify their needs and feed them whenever you find them crying. If you have been breastfeeding and have been offering breast milk of only one breast, you may need to start offering both breasts to feed your infant",
    "22- Watch sleeping patterns of your growing infant. Your baby can sleep anywhere between one to three hours during the day",
    "33- whenever your baby crying, attend your baby and give her all you attention",
    "44- You can tie wrist rattles on your baby’s wrists and let them gaze at the color and sound of the rattle",
    "55- Watch her coo and throw her hands around on hearing a loud noise. Talk with your dear little one"
    },
    {
    "11- As your baby is able to sit up more and hold their head up better, they may be able to tolerate feedings without burpings now",
    "22- Most insect repellents are safe to use on your baby once they are 2 months old, but you should always exercise caution and do your best to protect your baby naturally",
    "33- Babies under 6 months old cannot use sunscreen, so if you will be enjoying outdoor fun in the sun, you should keep your little one in the shade and use protective clothing, such as sun hats",
    "44- Babies cannot have honey until they are over 1 year old.",
    "55- ust like the past few months, you should aim to bathe your baby every two to three days. Your little one’s skin is still sensitive and too many baths may dry out their skin"
    },
    {
    "11- Give your little one plenty of time to explore the world around them while sticking to nap and bedtime routines that will help you both get the rest you need",
    "22- You’re likely still trying to adjust to life with a baby while trying to make time for adult things like hobbies and exercise—maybe even reading a book or going out to dinner every now then",
    "33- You should continue to introduce new foods and textures to your baby. Keep in mind, there is no rush and your little one might just take their time adjusting",
    "44- Your infant’s sleep might be disrupted for a month or so while they begin teething for the first time",
    "55-  If your baby’s first tooth didn’t begin to come in last month, get ready! Your child’s pediatrician will likely advise you to monitor your child’s teething symptoms, keep them comfortable and administer medication if needed for the pain, and begin oral hygiene"
    },
    {
    "11- Your child is probably taking at least a few steps on her own. About half of 15-month-olds can walk well. A few are even running or starting to learn to walk backwards!",
    "22- The babies of this age stat to say at least one word. Half can say at least two words. And some tots will have now ventured past \"dada\" and \"mama\" to form a growing vocabulary that includes words like \"dog,\" \"juice\" and— if you’re still breastfeeding \"boobies.\"",
    "33- First molars may be starting to erupt. For some kids, cutting teeth can be painful and bothersome. For others, you just happen to notice one day a new pearly white poking through the gums—no biggie",
    "44- Your child is starting to understand what everyday objects are used for—a broom is for sweeping and a wooden spoon is for stirring, for example",
    "55- should get 11 to 14 hours of sleep total in a 24-hour day. Wondering when your kid’s going to become a one-nap-a-day tot? Her sleep schedule will usually start to shift from two naps on its own right about now"
    }
    
};

int month[4][2] = {{0,3},{3,6}, {6,12},{12,24}};
int getAge(char birthDate[]){
    struct tm tm;
    time_t t;
    time_t ct;
    if (strptime(birthDate, "%A %b %d %H:%M:%S %Y", &tm) != NULL){
            tm.tm_isdst = -1;      
            t = mktime(&tm);
            time( &ct );
            double td =  difftime( ct, t );
            int totalseconds = (long) td;
            int agemonth = totalseconds /2592000;
            return agemonth;
    }else{
         return 0;
    }
}
int fetchMonth(){
    int index;
    int currentMonth = getAge(birth);
    for(int i=0;i<4;i++){
        if(currentMonth>month[i][0] && currentMonth<=month[i][1]){
           index = i;
            break;
        }else{
            index = 0;
        }
    }
    return index;
}

static uint8_t* create_message(int topic, int dur) {
     // initialize the buffer
     uint8_t tx_buffer[50] = { 0 };
     
     // DATA TO SEND (THE BELOW VALUES ARE THE ONES TO BE MODIFIED)
      char device[] = "infant";
     //int topic = 3; // topic identifier
    //  long int start = 1606037871;  // start reading
    //  long int end =   1606038090; // end reading
     
    // int durations = end - start;
     
     // Writing string data into a buffer
     sprintf((char*) tx_buffer, "{\"device\":\"%s\",\"topic\":%d,\"duration\":%d }", device, topic,dur);
     return tx_buffer;
}


// Send a message over LoRaWAN
static void send_message(uint8_t *tx_buffer) {
   
    int packet_len = strlen((char*) tx_buffer);

    printf("Sending %d bytes: \"%s\"\n", packet_len, tx_buffer);


    int16_t retcode = lorawan.send(MBED_CONF_LORA_APP_PORT, tx_buffer, packet_len, MSG_UNCONFIRMED_FLAG);

    // for some reason send() returns -1... I cannot find out why, the stack returns the right number. I feel that this is some weird Emscripten quirk
    if (retcode < 0) {
        retcode == LORAWAN_STATUS_WOULD_BLOCK ? printf("send - duty cycle violation\n")
                : printf("send() - Error code %d\n", retcode);
        return;
    }

    printf("%d bytes scheduled for transmission\n", retcode);
}

void display(string msg){
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf(msg.c_str());
}
void blinkWhiteLed(){
    whiteLed=!whiteLed;
}
void checkReadingTime(){
    time( &rawreadtime1 );
    readingDuration = rawreadtime1 - starreadttime;
}
void showMode2(){
    scrolling=0;
    string x="";
    if(scrollingState==0){
        x = content[fetchMonth()][0]+"\n";
    }else{
        x = content[fetchMonth()][currentIndex]+"\n";
    }
    display(x);
    time( &rawreadtime1 );
    starreadttime = rawreadtime1;
    ticker2.detach();
    ticker3.attach(ev_queue.event(&checkReadingTime),0.01f);
}
void sendData(){
        if(readingDuration>=5){
            send_message(create_message((currentIndex+1),readingDuration));
         printf("topic sent\n");
         printf("topic ID: %d Duration: %d \n",(currentIndex+1),readingDuration );
    }
}
void forwards(){
    display(topic[fetchMonth()][currentTopic].c_str());
    currentIndex = currentTopic;
     currentTopic++;
     if(currentTopic>4){
         currentTopic=0;
    }
}
void backwards(){
    display(topic[fetchMonth()][currentTopic].c_str());
    currentIndex = currentTopic;
     currentTopic--;
     if(currentTopic<0){
        currentTopic=4;
    }
}
void showTopic(){
   ticker.attach(ev_queue.event(&blinkWhiteLed), 1.0f);
    scrollingState=1;
    ticker2.detach();
    if(direction){
        blueLed=1;
        redLed=0;
        int i=0;
        currentTopic=5;
        ticker2.attach(ev_queue.event(&backwards),2.0f);
    }else{
        blueLed=0;
        redLed=1;
        int i=5;
        currentTopic=0;
        ticker2.attach(ev_queue.event(&forwards),2.0f);
    }
}

void showMode1(){
    ticker3.detach();
    sendData();
    readingDuration=0;
    lcd.cls();
    lcd.locate(0, 0);
    scrollingState=0;
    float temp = sht31.readTemperature();
    float humidity = sht31.readHumidity();
    lcd.printf("Temperature: %.2f C", temp);
    lcd.locate(3, 13);
    lcd.printf("Humidity: %.2f %%", humidity);
    scrolling=1;
    t.attach(ev_queue.event(&showTopic),3.0f);
}

void startup(){ 
    string msg = "Welcome to Infant Care \n";
    struct tm *info;
    time( &rawtime );
    info = localtime( &rawtime );
    display(msg);
    lcd.printf("%s", asctime(info));
    lcd.printf("Baby's age of %d months\n",getAge(birth));
    t.attach(ev_queue.event(&showMode1),5.0f);
}
void shutDown(){
    ticker2.detach();
    ticker4.detach();
    display("Reset to factory\n Wait for 10 seconds for fresh sturtup\n");
    direction=true;
    t2.attach(ev_queue.event(&startup),10.0f);
}
void checktime(){
    time( &rawtime1 );
    duration = rawtime1 - starttime;
    if(duration>=5){
        hold5=1;
        printf("shut down\n");
        t.detach();
        ticker2.detach();
        ticker4.detach();
        shutDown();
    }
    else if(duration>=3 && duration<5 && hold3==0){
        hold3=1;
        direction=!direction;
        scrolling=1;
        showTopic();
    }
}
void riseBtn(){
    time( &rawtime1 );
    starttime = rawtime1;
    ticker4.attach(ev_queue.event(&checktime),0.01f);
}
void fallBtn(){
    duration=0;
    hold3=0;
    ticker4.detach();
}

int main() {
       if (DEV_EUI[0] == 0x0 && DEV_EUI[1] == 0x0 && DEV_EUI[2] == 0x0 && DEV_EUI[3] == 0x0 && DEV_EUI[4] == 0x0 && DEV_EUI[5] == 0x0 && DEV_EUI[6] == 0x0 && DEV_EUI[7] == 0x0) {
        printf("Set your LoRaWAN credentials first!\n");
        return -1;
    }

    printf("Press BUTTON1 to send the current value of the temperature sensor!\n");

    // Enable trace output for this demo, so we can see what the LoRaWAN stack does
    mbed_trace_init();

    if (lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK) {
        printf("LoRa initialization failed!\n");
        return -1;
    }

    // Fire a message when the button is pressed
   // btn1.fall(ev_queue.event(&send_data_button_isr));
    directionBtn.rise(ev_queue.event(&riseBtn));
    directionBtn.fall(ev_queue.event(&fallBtn));
    modeSwith.rise(ev_queue.event(&showMode2));
    modeSwith.fall(ev_queue.event(&showMode1));

    // prepare application callbacks
    callbacks.events = mbed::callback(lora_event_handler);
    lorawan.add_app_callbacks(&callbacks);

    // Disable adaptive data rating
    if (lorawan.disable_adaptive_datarate() != LORAWAN_STATUS_OK) {
        printf("disable_adaptive_datarate failed!\n");
        return -1;
    }

    lorawan.set_datarate(5); // SF7BW125

    lorawan_connect_t connect_params;
    connect_params.connect_type = LORAWAN_CONNECTION_OTAA;
    connect_params.connection_u.otaa.dev_eui = DEV_EUI;
    connect_params.connection_u.otaa.app_eui = APP_EUI;
    connect_params.connection_u.otaa.app_key = APP_KEY;
    connect_params.connection_u.otaa.nb_trials = 3;

    lorawan_status_t retcode = lorawan.connect(connect_params);

    if (retcode == LORAWAN_STATUS_OK ||
        retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) {
    } else {
        printf("Connection error, code = %d\n", retcode);
        return -1;
    }

    printf("Connection - In Progress ...\r\n");

    // make your event queue dispatching events forever
    ev_queue.dispatch_forever();
    


    return 0;
    
    
   
}

// This is called from RX_DONE, so whenever a message came in
static void receive_message()
{
    uint8_t rx_buffer[50] = { 0 };
    int16_t retcode;
    retcode = lorawan.receive(MBED_CONF_LORA_APP_PORT, rx_buffer,
                              sizeof(rx_buffer),
                              MSG_CONFIRMED_FLAG|MSG_UNCONFIRMED_FLAG);

    if (retcode < 0) {
        printf("receive() - Error code %d\n", retcode);
        return;
    }

    printf("Data received on port %d (length %d): ", MBED_CONF_LORA_APP_PORT, retcode);

    for (uint8_t i = 0; i < retcode; i++) {
        printf("%02x ", rx_buffer[i]);
    }
    printf("\n");
}

// Event handler
static void lora_event_handler(lorawan_event_t event) {
    switch (event) {
        case CONNECTED:
            printf("Connection - Successful\n");
            startup();
            
            break;
        case DISCONNECTED:
            ev_queue.break_dispatch();
            printf("Disconnected Successfully\n");
            break;
        case TX_DONE:
            printf("Message Sent to Network Server\n");
            break;
        case TX_TIMEOUT:
        case TX_ERROR:
        case TX_CRYPTO_ERROR:
        case TX_SCHEDULING_ERROR:
            printf("Transmission Error - EventCode = %d\n", event);
            break;
        case RX_DONE:
            printf("Received message from Network Server\n");
            receive_message();
            break;
        case RX_TIMEOUT:
        case RX_ERROR:
            printf("Error in reception - Code = %d\n", event);
            break;
        case JOIN_FAILURE:
            printf("OTAA Failed - Check Keys\n");
            break;
        default:
            MBED_ASSERT("Unknown Event");
    }
}