iot
iot수업을 수강하면서 창문 자동 개폐 장치를 만들었다.
작동 원리는 이와 같다.
작동 원리는 이와 같다.
- arduino의 센서를 통해 온도와 습도를 측정하고 그 데이터를 aws iot core의 topic으로 publish하면 사전에 설정한 iot core의 rule을 통해서 aws s3에 저장한다.
- ✅ aws lambda의 트리거를
s3의 데이터 저장
으로 설정하여 aws lambda 함수를 작동시킨다. - ✅ aws lambda 함수는 사용자의 위치를 파악하여 해당 위치의 온도와 습도를 크롤링하는 함수이다.
- ✅ 해당 lmabda 함수의 destination으로 또 다른 lanbda 함수를 설정해놓는다.
- ✅ 두번째 lambda 함수는 s3에 저장한 온도, 습도 데이터와 크롤링함수를 통해 찾은 사용자 지역의 온도 및 습도를 비교하여 권고기준이 넘어가면 google fcm 을 통해서 android로 알림을 보내는 함수이다.
- android에서 사용자가 이벤트(open & close)를 발생시켜서 해당 데이터("open" or "close")를 s3에 저장하면
- ✅
s3의 데이터 저장
과 trigger로 연결된 또 다른 lambda함수를 통해 arduino의 endpoint로 사용자 명령을 전송한다. - arduino에서 받은 데이터를 가지고 모터를 작동시켜 문을 열고 닫는다.
1. lambda code - crawling-region
import json
import boto3
import botocore
### 위에는 s3 연결 패키지 아래는 크롤링 패키지
import requests
from bs4 import BeautifulSoup
source = requests.get('https://www.weather.go.kr/weather/observation/currentweather.jsp')
soup = BeautifulSoup(source.content,"html.parser")
table = soup.find('table',{'class':'table_develop3'})
data = []
## s3 버킷 저장
BUCKET_NAME = 'all-region-data'
KEY = 'all_location_data.txt'
s3_client = boto3.client('s3')
s3 = boto3.resource('s3')
def lambda_handler(event, context):
s3.Object(BUCKET_NAME, KEY).delete()
print("지역 온도 습도")
for tr in table.find_all('tr'):
tds = list(tr.find_all('td'))
for td in tds:
if td.find('a'):
point = td.find('a').text
temp = tds[5].text
humidity = tds[10].text
print("{0:<7} {1:<7} {2:<7}".format(point,temp,humidity))
data.append([point,temp,humidity])
## 버킷에 저장하는 코드
s3_client.put_object(Body=json.dumps(data, ensure_ascii=False), Bucket=BUCKET_NAME, Key=KEY)
2. lambda code - SendToAndroid
const http = require('https');
const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const src_bkt = 'sensor-esp32'
const src_key = 'location_data.txt'
const src_key2 = 'text.txt' // bme280에서 측정하는 값(온도, 습도)
const src_bkt_crawl = 'all-region-data'
const src_key_crawl = 'all_location_data.txt'
const src_key_time = 'alarm_current_time.txt' // 알림을 보내는 시간을 저장하는 txt파일
let outside_temp = false
let outside_humid = false
let date = new Date();
let hours = date.getHours()
let minutes = date.getMinutes(); // 현재 분
let time = hours + " " + minutes
let alarm_or_not = false // 알람 보낼지 말지 여부
exports.handler = async(event, context) => {
console.log(time)
var params = {
Bucket: src_bkt,
Key: src_key
};
var params2 = {
Bucket: src_bkt,
Key: src_key2
};
var params3 = {
Bucket: src_bkt_crawl,
Key: src_key_crawl
};
var params4 = { // 알림 보낼 시간 저장하기 위한 파람 --> 현재시간을 저장한다
Bucket: src_bkt,
Key: src_key_time,
Body: time
};
var params5 = { // 알림 보냈던 시간 불러오기 위한 파람
Bucket: src_bkt,
Key: src_key_time
};
const data = await s3.getObject(params).promise();
const data2 = await s3.getObject(params2).promise();
const data3 = await s3.getObject(params3).promise(); // 크롤링 파일에서 가져온 데이터
const data5 = await s3.getObject(params5).promise();
const response = {
statusCode: 200,
body: data.Body
};
const response2 = {
statusCode: 200,
body2: data2.Body
};
const response3 = {
statusCode: 200,
body3: data3.Body
};
const response5 = {
statusCode: 200,
body5: data5.Body
};
let alarm_current_hour = new Buffer.from(data5.Body).toString().split(" ")[0]; // 가장 최근에 알림을 보낸 시간
let alarm_current_minute = new Buffer.from(data5.Body).toString().split(" ")[1]; // 가장 최근에 알림을 보낸 분
let user_location = new Buffer.from(data.Body).toString().substring(1)
let local_temp = parseFloat(new Buffer.from(data2.Body).toString().split(',')[0]) // bme에서 측정한 온도
let local_humid = parseFloat(new Buffer.from(data2.Body).toString().split(',')[1])
let crawling_data = new Buffer.from(data3.Body).toString().split(',')
for(var i = 0; i<crawling_data.length; i++){
if(crawling_data[i].substring(3,5) == user_location) { // 사용자 지정 지역과 크롤링데이터에서 같은 이름의 지역을 찾으면.
outside_temp = parseFloat( (crawling_data[i+1]).substring(2, crawling_data[i+1].length-1))
outside_humid = parseFloat( (crawling_data[i+2]).substring(2, crawling_data[i+2].length-1))
}
}
console.log(outside_humid)
console.log(outside_temp)
console.log(time)
console.log(alarm_current_hour)
console.log(alarm_current_minute)
// 온도와 습도 시간을 측정하여 조건에 부합하면 s3에 현재시간 저장
if( (hours==alarm_current_hour && minutes - 30 > alarm_current_minute) || (hours>alarm_current_hour && minutes+30 > alarm_current_minute) ){ // 현재 시간과 s3에 저장된(마지막으로 알람을 보낸 시간)이 30분이상 차이가 나면 s3에 시간 갱신
if( (outside_temp > 5 && outside_temp < 24) && (local_temp < 15 || local_temp > 24) ) {
if( (outside_humid > 40 && outside_humid < 70) && (local_humid < 40 || local_humid > 70)){
alarm_or_not = true
const data4 = await s3.putObject(params4).promise(); // 현재 시각을 s3에 저장한다.
console.log(11111)
}
}
}
console.log(alarm_or_not + "----------")
//android에 알람보내기
return new Promise((resolve, reject) => {
const options = {
host: "fcm.googleapis.com",
path: "/fcm/send",
method: 'POST',
headers: {
'Authorization': 'key=AAAA-_cJn0E:APA91bH-WoFFOCgNIxsva_X3byhpNUHWFHu-7anS2mjjgfYRUhkYHpnydVemCIfBz85j3bxFrEwRVvqx0tQb_O5Vl8c06D4miqrei82Hx9XjgM39rNy9JJ09Ou6R0NKXbTvKqJ75r602',
'Content-Type': 'application/json',
},
};
const title="alert"
const body="문 여는 것을 권고합니다"
const req = http.request(options, (res) => {
resolve('success') ;
});
req.on('error', (e) => {
reject(e.message);
});
const reqBody = '{"to":"' + 'fDGVf22xSdmErsgVeXlQSm:APA91bEJZHu0PFox1k0k2evfu5ALvC_CTQb_J6tLff0UggcSF-U5EQgnwFD3DkILmQUUvODj0ukQQp3rK1ByX9eXZn6mC9yBQYSQoqyn4vnZolKQW3lKdu3Ch0buGrLNqLCAIIpCJBab' + '", "priority": "high", "notification": {"title": "' +title + '", "body": "'+body+'"}}';
if( alarm_or_not == true ){
if( (outside_temp > 5 && outside_temp < 24) && (local_temp < 15 || local_temp > 24) ) {
if( (outside_humid > 40 && outside_humid < 70) && (local_humid < 40 || local_humid > 70)){
req.write(reqBody);
alarm_or_not=false
}
}
}
req.end();
});
}
3. lambda code - sendDoorStatusToEsp
import json
import boto3
import botocore
BUCKET_NAME = 'onoff'
KEY = 'door.txt'
s3_client = boto3.client('s3')
def lambda_handler(event, context):
data = s3_client.get_object(Bucket=BUCKET_NAME, Key=KEY)
content = data['Body'].read()
client = boto3.client('iot-data', region_name='ap-northeast-2')
# Change topic, qos and payload
response = client.publish(
topic = 'iot/lambda/testing',
qos=0,
payload = content
)
print(content)
return {
'statusCode': 200,
'body': json.dumps(content.decode('UTF-8'))
}
✋ aws의 여러기능을 써보고 충분히 이해하는데 있어서 정말 중요한 프로젝트였다. aws의 기능은 너무나도 많기 때문에 앞으로 서버공부하는데 더 많은 기능을 써보고 싶다.
✋ 시연동영상