Rushikesh MalakwadeShivraj Jawade
Published © MIT

Parking Availability System

This is an application that helps inform users about parking space availability in a car park. This device operates using IoT.

BeginnerProtip6 hours2,594
Parking Availability System

Things used in this project

Hardware components

AWS CloudWatch
Amazon Web Services AWS CloudWatch
×1
Marvell MW302 IoT Starter Kit
Marvell MW302 IoT Starter Kit
×1
IR Transceiver
×1
Female/Female Jumper Wires
Female/Female Jumper Wires
×1
Proximity Sensor
Proximity Sensor
×1

Software apps and online services

AWS SNS
Amazon Web Services AWS SNS

Story

Read more

Schematics

Circuit Diagram

connect mw302 starter kit with proximity sensor using female to female connectors

Code

code for parking_system

C/C++
/*
 *  Copyright (C) 2008-2015, Marvell International Ltd.
 *  All Rights Reserved.
 */
/*
 *Parking space availability Application
 *
 * Summary:
 *
 * Application demonstrates the available space information communication with the Thing
 * Shadow over MQTT. Using the web application, Configure the device to thing
 * shadow or any other shadow using its Thing name.
 *
 * Device publishes the changed state using proximity ir sensor.
 *
 *
 * The serial console is set on UART-0.
 *
 * A serial terminal minicom can be used to see the program output.
 */


/*header files*/
#include <wm_os.h>
#include <wmstdio.h>
#include <wmtime.h>
#include <wmsdk.h>
#include <led_indicator.h>
#include <board.h>
#include <push_button.h>
#include <aws_iot_mqtt_interface.h>
#include <aws_iot_shadow_interface.h>
#include <aws_utils.h>
#include <aws_iot_config.h>
#include "aws_starter_root_ca_cert.h"

/*cloud state*/
enum state {
	AWS_CONNECTED = 1,
	AWS_RECONNECTED,
	AWS_DISCONNECTED
};

/*Global declarations*/

/* These hold each pushbutton's count, updated in the callback ISR */
static volatile uint32_t sensor1_count;
static volatile uint32_t sensor1_count_prev = -1;
static volatile uint32_t sensor2_count;
static volatile uint32_t sensor2_count_prev = -1;



static MQTTClient_t mqtt_client;
static enum state device_state;

/* Thread handle */
static os_thread_t aws_starter_thread;
/* Buffer to be used as stack */
static os_thread_stack_define(aws_starter_stack, 12 * 1024);
/* aws iot url */
static char url[128];

#define MICRO_AP_SSID                "PARKING_SYSTEM"
#define MICRO_AP_PASSPHRASE          "marvellwm"
#define AMAZON_ACTION_BUF_SIZE       100
#define VAR_SENSOR1_PROPERTY        "car_no_at_1"
#define VAR_SENSOR2_PROPERTY        "car_no_at_2"
#define RESET_TO_FACTORY_TIMEOUT     5000
#define BUFSIZE                      128
#define MAX_MAC_BYTES                6

/* callback function invoked on reset to factory */
static void device_reset_to_factory_cb()
{
	invoke_reset_to_factory();
}

/* board_button_2() is configured to perform reset to factory,
 * when pressed for more than 5 seconds.
 */
static void configure_reset_to_factory()
{
	input_gpio_cfg_t pushbutton_reset_to_factory = {
		.gpio = board_button_2(),
		.type = GPIO_ACTIVE_LOW
	};
	push_button_set_cb(pushbutton_reset_to_factory,
			   device_reset_to_factory_cb,
			   RESET_TO_FACTORY_TIMEOUT, 0, NULL);
}

/* callback function invoked when pushbutton_a is pressed */
static void pushbutton_a_cb()
{
	if (sensor1_count_prev == sensor1_count)
		sensor1_count++;
}

/* callback function invoked when pushbutton_b is pressed */
static void pushbutton_b_cb()
{
	if (sensor2_count_prev == sensor2_count)
		sensor2_count++;
}

/* Configure led and pushbuttons with callback functions */
static void configure_led_and_button()
{
	/* respective GPIO pins for pushbuttons and leds are defined in
	 * board file.
	 */
	input_gpio_cfg_t pushbutton_a = {
		.gpio = board_button_1(),
		.type = GPIO_ACTIVE_LOW
	};
	input_gpio_cfg_t pushbutton_b = {
		.gpio = board_button_2(),
		.type = GPIO_ACTIVE_LOW
	};

	push_button_set_cb(pushbutton_a,
			   pushbutton_a_cb,
			   100, 0, NULL);
	push_button_set_cb(pushbutton_b,
			   pushbutton_b_cb,
			   100, 0, NULL);
}


static char client_cert_buffer[AWS_PUB_CERT_SIZE];
static char private_key_buffer[AWS_PRIV_KEY_SIZE];
#define THING_LEN 126
#define REGION_LEN 16
static char thing_name[THING_LEN];
static char client_id[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES];
/* populate aws shadow configuration details */
static int aws_starter_load_configuration(ShadowParameters_t *sp)
{
	int ret = WM_SUCCESS;
	char region[REGION_LEN];
	uint8_t device_mac[MAX_MAC_BYTES];
	memset(region, 0, sizeof(region));

	/* read configured thing name from the persistent memory */
	ret = read_aws_thing(thing_name, THING_LEN);
	if (ret != WM_SUCCESS) {
		wmprintf("Failed to configure thing. Returning!\r\n");
		return -WM_FAIL;
	}
	sp->pMyThingName = thing_name;

	/* read device MAC address */
	ret = read_aws_device_mac(device_mac);
	if (ret != WM_SUCCESS) {
		wmprintf("Failed to read device mac address. Returning!\r\n");
		return -WM_FAIL;
	}
	/* Unique client ID in the format prefix-6 byte MAC address */
	snprintf(client_id, MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES,
		 "%s-%02x%02x%02x%02x%02x%02x", AWS_IOT_MQTT_CLIENT_ID,
		 device_mac[0], device_mac[1], device_mac[2],
		 device_mac[3], device_mac[4], device_mac[5]);
	sp->pMqttClientId = client_id;

	/* read configured region name from the persistent memory */
	ret = read_aws_region(region, REGION_LEN);
	if (ret == WM_SUCCESS) {
		snprintf(url, sizeof(url), "data.iot.%s.amazonaws.com",
			 region);
	} else {
		snprintf(url, sizeof(url), "data.iot.%s.amazonaws.com",
			 AWS_IOT_MY_REGION_NAME);
	}
	sp->pHost = url;
	sp->port = AWS_IOT_MQTT_PORT;
	sp->pRootCA = rootCA;

	/* read configured certificate from the persistent memory */
	ret = read_aws_certificate(client_cert_buffer, AWS_PUB_CERT_SIZE);
	if (ret != WM_SUCCESS) {
		wmprintf("Failed to configure certificate. Returning!\r\n");
		return -WM_FAIL;
	}
	sp->pClientCRT = client_cert_buffer;

	/* read configured private key from the persistent memory */
	ret = read_aws_key(private_key_buffer, AWS_PRIV_KEY_SIZE);
	if (ret != WM_SUCCESS) {
		wmprintf("Failed to configure key. Returning!\r\n");
		return -WM_FAIL;
	}
	sp->pClientKey = private_key_buffer;

	return ret;
}

void shadow_update_status_cb(const char *pThingName, ShadowActions_t action,
			     Shadow_Ack_Status_t status,
			     const char *pReceivedJsonDocument,
			     void *pContextData) {

	if (status == SHADOW_ACK_TIMEOUT) {
		wmprintf("Shadow publish state change timeout occurred\r\n");
	} else if (status == SHADOW_ACK_REJECTED) {
		wmprintf("Shadow publish state change rejected\r\n");
	} else if (status == SHADOW_ACK_ACCEPTED) {
		wmprintf("Shadow publish state change accepted\r\n");
	}
}

/* This function will get invoked when led state change request is received */

/* Publish thing state to shadow */
int aws_publish_property_state(ShadowParameters_t *sp)
{
	char buf_out[BUFSIZE];
	char state[BUFSIZE];
	char *ptr = state;
	int ret = WM_SUCCESS;

	memset(state, 0, BUFSIZE);
	if (sensor1_count_prev != sensor1_count) {
		snprintf(buf_out, BUFSIZE, ",\"%s\":%lu", VAR_SENSOR1_PROPERTY,
			 sensor1_count);
		strcat(state, buf_out);
		sensor1_count_prev = sensor1_count;
	}
	if (sensor2_count_prev != sensor2_count) {
		snprintf(buf_out, BUFSIZE, ",\"%s\":%lu", VAR_SENSOR2_PROPERTY,
				sensor2_count);
		strcat(state, buf_out);
		sensor2_count_prev = sensor2_count;
	}

	if (*ptr == ',')
		ptr++;
	if (strlen(state)) {
		snprintf(buf_out, BUFSIZE, "{\"state\": {\"reported\":{%s}}}",
			 ptr);
		wmprintf("Publishing '%s' to AWS\r\n", buf_out);

		/* publish incremented value on pushbutton press on
		 * configured thing */
		ret = aws_iot_shadow_update(&mqtt_client,
					    sp->pMyThingName,
					    buf_out,
					    shadow_update_status_cb,
					    NULL,
					    10, true);
	}
	return ret;
}

/* application thread */
static void aws_starter_demo(os_thread_arg_t data)
{
	int led_state = 0, ret;
	jsonStruct_t led_indicator;
	ShadowParameters_t sp;

	aws_iot_mqtt_init(&mqtt_client);

	ret = aws_starter_load_configuration(&sp);
	if (ret != WM_SUCCESS) {
		wmprintf("aws shadow configuration failed : %d\r\n", ret);
		goto out;
	}

	ret = aws_iot_shadow_init(&mqtt_client);
	if (ret != WM_SUCCESS) {
		wmprintf("aws shadow init failed : %d\r\n", ret);
		goto out;
	}

	ret = aws_iot_shadow_connect(&mqtt_client, &sp);
	if (ret != WM_SUCCESS) {
		wmprintf("aws shadow connect failed : %d\r\n", ret);
		goto out;
	}

	/* indication that device is connected and cloud is started */
	led_on(board_led_2());
	wmprintf("Cloud Started\r\n");

	/* configures property of a thing */

	led_indicator.pData = &led_state;
	led_indicator.pKey = "led";
	led_indicator.type = SHADOW_JSON_INT8;

	/* subscribes to delta topic of the configured thing */
	ret = aws_iot_shadow_register_delta(&mqtt_client, &led_indicator);
	if (ret != WM_SUCCESS) {
		wmprintf("Failed to subscribe to shadow delta %d\r\n", ret);
		goto out;
	}

	while (1) {
		/* Implement application logic here */

		if (device_state == AWS_RECONNECTED) {
			ret = aws_iot_shadow_init(&mqtt_client);
			if (ret != WM_SUCCESS) {
				wmprintf("aws shadow init failed: "
					 "%d\r\n", ret);
				goto out;
			}
			ret = aws_iot_shadow_connect(&mqtt_client, &sp);
			if (ret != WM_SUCCESS) {
				wmprintf("aws shadow reconnect failed: "
					 "%d\r\n", ret);
				goto out;
			} else {
				device_state = AWS_CONNECTED;
				led_on(board_led_2());
				ret = aws_iot_shadow_register_delta(
					&mqtt_client, &led_indicator);
				wmprintf("Reconnected to cloud\r\n");
			}
		}
		aws_iot_shadow_yield(&mqtt_client, 10);
		ret = aws_publish_property_state(&sp);
		if (ret != WM_SUCCESS)
			wmprintf("Sending property failed\r\n");
		os_thread_sleep(100);
	}

	ret = aws_iot_shadow_disconnect(&mqtt_client);
	if (NONE_ERROR != ret) {
		wmprintf("aws iot shadow error %d\r\n", ret);
	}

out:
	os_thread_self_complete(NULL);
	return;
}

void wlan_event_normal_link_lost(void *data)
{
	/* led indication to indicate link loss */
	aws_iot_shadow_disconnect(&mqtt_client);
	device_state = AWS_DISCONNECTED;
}

void wlan_event_normal_connect_failed(void *data)
{
	/* led indication to indicate connect failed */
	aws_iot_shadow_disconnect(&mqtt_client);
	device_state = AWS_DISCONNECTED;
}

/* This function gets invoked when station interface connects to home AP.
 * Network dependent services can be started here.
 */
void wlan_event_normal_connected(void *data)
{
	int ret;
	/* Default time set to 1 April 2016 */
	time_t time = 1459468800;

	wmprintf("Connected successfully to the configured network\r\n");

	if (!device_state) {
		/* set system time */
		wmtime_time_set_posix(time);

		/* create cloud thread */
		ret = os_thread_create(
			/* thread handle */
			&aws_starter_thread,
			/* thread name */
			"awsStarterDemo",
			/* entry function */
			aws_starter_demo,
			/* argument */
			0,
			/* stack */
			&aws_starter_stack,
			/* priority */
			OS_PRIO_3);
		if (ret != WM_SUCCESS) {
			wmprintf("Failed to start cloud_thread: %d\r\n", ret);
			return;
		}
	}

	if (!device_state)
		device_state = AWS_CONNECTED;
	else if (device_state == AWS_DISCONNECTED)
		device_state = AWS_RECONNECTED;
}

int main()
{
	/* initialize the standard input output facility over uart */
	if (wmstdio_init(UART0_ID, 0) != WM_SUCCESS) {
		return -WM_FAIL;
	}

	/* initialize gpio driver */
	if (gpio_drv_init() != WM_SUCCESS) {
		wmprintf("gpio_drv_init failed\r\n");
		return -WM_FAIL;
	}

	wmprintf("Build Time: " __DATE__ " " __TIME__ "\r\n");
	wmprintf("\r\n#### AWS STARTER DEMO ####\r\n\r\n");

	/* configure pushbutton on device to perform reset to factory */
	configure_reset_to_factory();
	/* configure led and pushbutton to communicate with cloud */
	configure_led_and_button();

	/* This api adds aws iot configuration support in web application.
	 * Configuration details are then stored in persistent memory.
	 */
	enable_aws_config_support();

	/* This api starts micro-AP if device is not configured, else connects
	 * to configured network stored in persistent memory. Function
	 * wlan_event_normal_connected() is invoked on successful connection.
	 */
	wm_wlan_start(MICRO_AP_SSID, MICRO_AP_PASSPHRASE);
	return 0;
}

Credits

Rushikesh Malakwade

Rushikesh Malakwade

1 project • 0 followers
Shivraj Jawade

Shivraj Jawade

1 project • 0 followers

Comments