Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Sai YamanoorSrihari Yamanoor
Created March 31, 2024

Emergency Nasal Spray Medication Dispenser

This project enables creating Resilient Cities by making nasal spray that prevents narcotic overdoses accessible to citizens.

19
Emergency Nasal Spray Medication Dispenser

Things used in this project

Hardware components

AVR IoT Mini Cellular Board
Microchip AVR IoT Mini Cellular Board
×1
Switch Actuator, Head for spring return push-button
Switch Actuator, Head for spring return push-button
×1
Gravity: Digital 5A Relay Module
DFRobot Gravity: Digital 5A Relay Module
×1
Wooden Box
×1
Solenoid Lock 12V
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

System Schematic

Amazon Lambda Code

Code

Arduino Code

Arduino
/**
   This example connects to the device specific endpoint in AWS in order to
   publish and retrieve MQTT messages.
*/

#include <Arduino.h>

#include <ecc608.h>
#include <led_ctrl.h>
#include <log.h>
#include <lte.h>
#include <mqtt_client.h>


// documentation.
const char MQTT_SUB_TOPIC_FMT[] PROGMEM = "$aws/things/%s/shadow/update/delta";
const char MQTT_PUB_TOPIC_FMT[] PROGMEM = "%s/sensors";

char mqtt_sub_topic[128];
char mqtt_pub_topic[128];

bool initTopics() {
  ATCA_STATUS status = ECC608.begin();

  if (status != ATCA_SUCCESS) {
    Log.errorf(F("Failed to initialize ECC, error code: %X\r\n"), status);
    return false;
  }

  // Find the thing ID and set the publish and subscription topics
  uint8_t thing_name[128];
  size_t thing_name_length = sizeof(thing_name);

  status =
    ECC608.readProvisionItem(AWS_THINGNAME, thing_name, &thing_name_length);

  if (status != ATCA_SUCCESS) {
    Log.errorf(
      F("Could not retrieve thingname from the ECC, error code: %X\r\n"),
      status);
    return false;
  }

  snprintf_P(mqtt_sub_topic,
             sizeof(mqtt_sub_topic),
             MQTT_SUB_TOPIC_FMT,
             thing_name);
  snprintf_P(mqtt_pub_topic,
             sizeof(mqtt_pub_topic),
             MQTT_PUB_TOPIC_FMT,
             thing_name);

  return true;
}

static volatile bool button_pressed = false;
uint8_t medicationCount = 50;
/**
   @brief Gets called when the SW0 button is pressed.
*/
static void buttonInterrupt(void) {
  button_pressed = true;
}

static void sendMessage() {

  // Attempt to connect to AWS
  if (MqttClient.beginAWS()) {
    MqttClient.subscribe(mqtt_sub_topic);
  } else {
    Log.error(F("Failed to connect to AWS"));
    while (1) {}
  }



  const bool published_successfully =
    MqttClient.publish(mqtt_pub_topic, "{\"ButtonPress\":1}");

  if (published_successfully) {
    Log.info(F("Published message"));
  } else {
    Log.error(F("Failed to publish\r\n"));
  }

  delay(4000);

  String message = MqttClient.readMessage(mqtt_sub_topic);

  // Read message will return an empty string if there were no new
  // messages, so anything other than that means that there were a
  // new message
  if (message != "") {
    Log.infof(F("Got new message: %s\r\n"), message.c_str());
  }

  


  Log.info(F("Closing MQTT connection"));

  MqttClient.end();
  
}
void setup() {
  Log.begin(115200);
  LedCtrl.begin();
  LedCtrl.startupCycle();

  pinConfigure(PIN_PD2, PIN_DIR_INPUT | PIN_PULLUP_ON);
  attachInterrupt(PIN_PD2, buttonInterrupt, FALLING);

  pinConfigure(PIN_PA7, PIN_DIR_OUTPUT);
  digitalWrite(PIN_PA7, LOW);

  Log.info(F("Starting MQTT for AWS example\r\n"));

  if (!initTopics()) {
    Log.error(F("Unable to initialize the MQTT topics. Stopping..."));
    while (1) {}
  }

  if (!Lte.begin()) {
    Log.error(F("Failed to connect to operator"));
    while (1) {}
  }



  
}


void loop() {
  if (button_pressed)
  {
    digitalWrite(PIN_PA7, HIGH);
    sendMessage();
    button_pressed = false;
    digitalWrite(PIN_PA7, LOW);
  }
  
  
}

Amazon Lambda Function Code

Python
import boto3 # AWS SDK for python
import json  # JSON encoder and decoder

# Name of the AWS IoT Core thing that should be notified about process anomalies
notificationThing = 'a235ad80c08683026e4bdbb937a5e97c430bc596'

cloudwatch = boto3.client('cloudwatch')

# Define payload attributes that may be changed based on device message schema
ATTRIBUTES = ['ButtonPress']

# Define CloudWatch namespace
CLOUDWATCH_NAMESPACE = "thing2/MonitorMetrics"

# Define function to publish the metric data to CloudWatch
def cw(topic, metricValue, metricName):
    metric_data = {
        'MetricName': metricName,
        'Dimensions': [{'Name': 'topic', 'Value': topic}],
        'Unit': 'None',
        'Value': metricValue,
        'StorageResolution': 1
    }

    cloudwatch.put_metric_data(MetricData=[metric_data],Namespace=CLOUDWATCH_NAMESPACE)
    return

# Main function
def lambda_handler(event, context):
    # Initialize dictionary for state variables
    dict = {}

    if event['ButtonPress'] == 1:
        dict['acknowledge'] = 1

    update_shadow(dict, notificationThing)
    
    for e in event:
        print("Received a message: {}".format(str(e)))
        # print(e) # Potential test point

        # Iterate through each attribute we'd like to publish
        for attribute in ATTRIBUTES:
            # Validate the event payload contains the desired attribute
            if attribute in e:
                print("publishing {} to CloudWatch".format(attribute))
                cw("AVR-IoT", event[attribute], attribute)
    return event

# Updates the device shadow of the specified thing_name
def update_shadow(state_dict, thing_name):

    # Construct payload and convert it to JSON format
    payload = {
        "state": {
            "desired": state_dict
        }
    }
    JSON_payload = json.dumps(payload)

    # Initialize AWS IoT Core SDK communicaiton client
    IoT_client = boto3.client('iot-data', 'us-east-1')

    # Send shadow update request
    response = IoT_client.update_thing_shadow(thingName=thing_name,payload=JSON_payload)
    
    # Create an SNS client to send notification
    sns = boto3.client('sns')
    
    # Format text message from data
    message_text = "Please dispense help to 123 Main Street, Kansas City, USA"

    # Publish the formatted message
    response2 = sns.publish(
            TopicArn = "arn:aws:sns:us-east-1:450888670274:MyAlert",
            Message = message_text
        )
    
    return response

Credits

Sai Yamanoor

Sai Yamanoor

11 projects • 10 followers
I am a hardware engineer. I like to design PCBs and build exciting gadgets.
Srihari Yamanoor

Srihari Yamanoor

2 projects • 0 followers
Mechanical Engineer, DIY Champ!

Comments