Hardware components | ||||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
Software apps and online services | ||||||
![]() |
| |||||
| ||||||
| ||||||
| ||||||
|
The following tools are required to run this demonstration.
- KETI Mobius Platform
- Arduino IDE
- Mosquitto
- Postman
- MySQL
- Node.js
You will also need an implementation of oneM2M platform. Different platforms exist, we can cite some:
- KETIMobius: An open-source implementation in Node.js (link)
- Arduino IDE:(link)
- Mosquitto:(link)
- Postman:(link)
- MySQL:(link)
- Node.js:(link)
The Arduino code is below.
4.1 Schematics
Connect the HeartRate sensor, Temp&Humi sensor, Monoxide&Methan gas sensor, Proximity sensor, Speaker module to Arduino Nano 33 IoT board.
- Breadboard
- Arduino Nano 33 IoT
- Temp&Humi sensor
- Monoxide&Methan gas sensor
- Proximity sensor
- Speaker module
4.2 Appearance of Device
4.3 Arduino code
A code for sensing sensors configured on a helmet.
4.4 Arduino SerialMonitor
This is the resource design of the worker.
Next, This is the resource design of the zone.
This page is an worker registration page.
The following is the worker inquiry page. You can check the list of workers, check the status of work by worker, check details, monitor, delete workers, etc.
This is the worker's detailed inquiry page. You can check the worker's details, current location, and dangerous situation.
This is the worker monitoring page. You can check the worker's current location and dangerous situation, temperature and humidity, and harmful gas levels on a graph.
This is the zone monitoring page. You can check the workshop map, and you can check what kind of workers are in each area.
In addition, the latest numerical values of temperature, humidity, methane gas, and carbon monoxide for each zone can be checked in a graph.
If a certain number or higher is measured for each zone, please send an alarm message to the bottom right. Monitoring is possible in real time.
It was also tested with a virtual device.
As a result, it can be confirmed that it is operating properly.
7. Demonstration VideoLet's watch the demonstration video.
8. Expectation Effectiveness- Prevent forgery and alteration of the access list
- Worker evacuation notification
- Rescue quickly
- Prevention of secondary accidents
By automating the list of visitors to the field, it is possible to increase the convenience of list management and prevent forgery and alteration.
And you can monitor and identify risks that are difficult for workers to recognize with a helmet and respond quickly.
const path = 'http://192.168.56.1:7579/Mobius'
// ngrok
// ngrok uri
//const path = 'http://b5bc-180-65-158-66.ngrok.io/Mobius'
// ### <ae> ###
function selectAe(ae_resource){
console.log("<ae> : " + ae_resource);
let uri = path + '/' + ae_resource;
fetch(uri, {
method: 'GET',
headers: {
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':'admin',
'Content-Type': 'application/json'
}
})
.then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => console.log(data));
}
else {
alert(' .');
console.error(res);
}
}).catch(err => console.error(err));
}
function createAe(ae_resource, ae_api){
console.log("<ae> : " + ae_resource);
let uri = path;
let item = {
"m2m:ae" : {
"rn": ae_resource,
"api": ae_api,
"rr": true
}
}
fetch(uri, {
method: 'POST',
headers: {
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':ae_resource,
'Content-Type': 'application/json;ty=2',
'Content-Length':'<calculated when request is sent>'
},
body: JSON.stringify(item)
})
.then((res) => {
if (res.statusText == 'OK' || res.statusText == 'Created') {
res.json().then(data => console.log(data));
}
else {
alert(' .');
console.error(res);
}
}).catch(err => console.error(err));
}
function deleteAe(ae_resource){
console.log("<ae> : " + ae_resource);
let uri = path + '/' + ae_resource;
fetch(uri, {
method: 'DELETE',
headers: {
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':ae_resource,
'Content-Type': 'application/json;ty=2',
'Content-Length':'<calculated when request is sent>'
}
})
.then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
console.log(data);
location.reload();
});
}
else {
alert(' .');
console.error(res);
}
}).catch(err => console.error(err));
}
// ### <cnt> ###
function selectCnt(ae_resource, cnt_resource){
console.log("<cnt> : " + ae_resource + '/' + cnt_resource);
let uri = path + '/' + ae_resource + '/' + cnt_resource;
fetch(uri, {
method: 'GET',
headers: {
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':'admin',
'Content-Type': 'application/json'
}
})
.then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => console.log(data));
}
else {
alert(' .');
console.error(res);
}
}).catch(err => console.error(err));
}
function createCnt(ae_resource, cnt_resource, mni, con='no_cin'){ // <cnt> , con <cin>
console.log("<cnt> : " + ae_resource + '/' + cnt_resource);
let uri = path + '/' + ae_resource;
let item = {
"m2m:cnt" : {
"rn": cnt_resource,
"mni": mni
}
};
fetch(uri, {
method: 'POST',
headers: {
'Content-Type': 'application/json; ty=3',
'Content-Length':'<calculated when request is sent>',
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin': cnt_resource
},
body: JSON.stringify(item)
})
.then((res) => {
if (res.statusText == 'OK' || res.statusText == 'Created') {
res.json().then(data => console.log(data));
if(con != 'no_cin'){
createCin(ae_resource, cnt_resource, con);
}
}
else {
alert(' .');
console.error(res);
}
}).catch(err => console.error(err));
}
function deleteCnt(ae_resource, cnt_resource){
console.log("<cnt> : " + ae_resource + '/' + cnt_resource);
let uri = path + '/' + ae_resource + '/' + cnt_resource;
fetch(uri, {
method: 'DELETE',
headers: {
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':cnt_resource,
'Content-Type': 'application/json;ty=3',
'Content-Length':'<calculated when request is sent>'
}
})
.then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => console.log(data));
}
else {
alert(' .');
console.error(res);
}
}).catch(err => console.error(err));
}
// ### <grp> ###
async function selectGrpAsync(ae_resource, grp_resource) {
console.log('selectGrpAsync() ');
let uri = path + '/'+ae_resource+'/'+grp_resource+'/fopt';
if(ae_resource == 'Zone'){
uri = path + '/' + grp_resource + '/fopt';
}
let response = await fetch(uri, {
method: 'GET',
headers: {
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':'admin',
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response;
}
function selectGrp(ae_resource, grp_resource, mode = 0){ // mode=0 : , mode='fopt' : fopt( )
console.log("<grp> : " + ae_resource + '/' + grp_resource + ' mode:' + mode);
let uri = path + '/' + ae_resource + '/' + grp_resource;
if(mode == 'fopt'){
uri += '/fopt'
}
fetch(uri, {
method: 'GET',
headers: {
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':'admin',
'Content-Type': 'application/json'
}
})
.then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => console.log(data));
}
else {
alert(' .');
console.error(res);
}
}).catch(err => console.error(err));
}
function createGrp(ae_resource, mode = 'biogrp'){ // mode='biogrp' : , mode='entgrp' :
console.log("<grp> : " + ae_resource + '/' + mode);
let item = {};
if (mode == 'biogrp'){
item = {
"m2m:grp" : {
"rn": 'biogrp',
"mid": [
"Mobius/"+ae_resource+"/location/la",
"Mobius/"+ae_resource+"/heartrate/la",
"Mobius/"+ae_resource+"/danger/la"
],
"mnm":10
}
};
}
else if(mode == 'entgrp'){
item = {
"m2m:grp" : {
"rn": 'entgrp',
"mid": [
"Mobius/"+ae_resource+"/temperature/la",
"Mobius/"+ae_resource+"/humidity/la",
"Mobius/"+ae_resource+"/methane/la",
"Mobius/"+ae_resource+"/cmonoxide/la"
],
"mnm":10
}
};
}
else if(mode == 'notegrp'){
item = {
"m2m:grp" : {
"rn": 'notegrp',
"mid": [
"Mobius/"+ae_resource+"/name/la",
"Mobius/"+ae_resource+"/hp/la",
"Mobius/"+ae_resource+"/location/la"
],
"mnm":10
}
};
}
else{
alert(" .");
return;
}
let uri = path + '/' + ae_resource;
fetch(uri, {
method: 'POST',
headers: {
'Content-Type': 'application/json;ty=9',
'Content-Length':'<calculated when request is sent>',
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin': mode
},
body: JSON.stringify(item)
})
.then((res) => {
if (res.statusText == 'OK' || res.statusText == 'Created') {
res.json().then(data => console.log(data));
}
else {
alert(' .');
console.error(res);
}
}).catch(err => console.error(err));
}
function deleteGrp(ae_resource, grp_resource){
console.log("<grp> : " + ae_resource + '/' + grp_resource);
let uri = path + '/' + ae_resource + '/' + grp_resource;
fetch(uri, {
method: 'DELETE',
headers: {
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':grp_resource,
'Content-Type': 'application/json;ty=9',
'Content-Length':'<calculated when request is sent>'
}
})
.then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => console.log(data));
}
else {
alert(' .');
console.error(res);
}
}).catch(err => console.error(err));
}
// ### <cin> ###
function selectCin(ae_resource, cnt_resource, mode=0){ // mode=0: , mode='la':con
console.log("<cin> : " + ae_resource + '/' + cnt_resource);
let uri = path + '/' + ae_resource + '/' + cnt_resource;
if(mode == 'la'){
uri += '/la'
}
else{
uri += '?rcn=4&ty=4'
}
fetch(uri, {
method: 'GET',
headers: {
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':'admin',
'Content-Type': 'application/json;ty=4',
'Content-Length':'<calculated when request is sent>'
}
})
.then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => console.log(data));
}
else {
alert(' .');
console.error(res);
}
}).catch(err => console.error(err));
}
async function selectCinAsync(ae_resource, cnt_resource, mode=0) {
console.log("<cin> : " + ae_resource + '/' + cnt_resource);
let uri = path + '/' + ae_resource + '/' + cnt_resource;
if(mode == 'la'){
uri += '/la'
}
else{
//uri += '?rcn=4&ty=4&lim=15' // lim=15 15 ..
uri += '?rcn=4&ty=4'
}
let response = await fetch(uri, {
method: 'GET',
headers: {
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':'admin',
'Content-Type': 'application/json;ty=4',
'Content-Length':'<calculated when request is sent>'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response;
}
function createCin(ae_resource, cnt_resource, con){
console.log("<cin> : " + ae_resource + '/' + cnt_resource + '/' + con);
let uri = path + '/' + ae_resource + '/' + cnt_resource;
let item = {
"m2m:cin": {
"con": con
}
};
fetch(uri, {
method: 'POST',
headers: {
'Content-Type': 'application/json;ty=4',
'Content-Length':'<calculated when request is sent>',
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin': cnt_resource
},
body: JSON.stringify(item)
})
.then((res) => {
if (res.statusText == 'OK' || res.statusText == 'Created') {
res.json().then(data => console.log(data));
}
else {
alert(' .');
console.error(res);
}
}).catch(err => console.error(err));
}
async function createCinAsync(ae_resource, cnt_resource, con) {
console.log("<cin> : " + ae_resource + '/' + cnt_resource + '/' + con);
let uri = path + '/' + ae_resource + '/' + cnt_resource;
let item = {
"m2m:cin": {
"con": con
}
};
let response = await fetch(uri, {
method: 'POST',
headers: {
'Content-Type': 'application/json;ty=4',
'Content-Length':'<calculated when request is sent>',
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin': cnt_resource
},
body: JSON.stringify(item)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Smart Working Environment Monitoring Service</title>
<!-- Bootstrap core CSS -->
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom fonts for this template -->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Merriweather:400,300,300italic,400italic,700,700italic,900,900italic' rel='stylesheet' type='text/css'>
<!-- Plugin CSS -->
<link href="vendor/magnific-popup/magnific-popup.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="css/creative.min.css" rel="stylesheet">
</head>
<style>
body {
padding-bottom: calc(10rem - 56px);
background-image: url(img/header.jpg);
background-size: cover;
}
</style>
<body id="page-top">
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
<div class="container">
<a class="navbar-brand js-scroll-trigger" href="index.html">Home</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="registration.html">Worker Registration</a>
</li>
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="users.html">Worker Inquire</a>
</li>
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="zone-monitoring.html">Zone Moniroting</a>
</li>
</ul>
</div>
</div>
</nav>
<header class="masthead text-center text-white d-flex">
<div class="container my-auto">
<div class="row">
<div class="col-lg-10 mx-auto">
<h1 class="text-uppercase">
<strong>Smart Working Environment Monitoring Service</strong>
</h1>
<hr>
</div>
<div class="col-lg-8 mx-auto">
<p class="text-faded mb-5">Lee yelim / Shin jeongseop</p>
<p class="text-faded" style="font-size: small">Mobi-Hero</p>
</div>
</div>
</div>
</header>
<!-- Bootstrap core JavaScript -->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Plugin JavaScript -->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<script src="vendor/scrollreveal/scrollreveal.min.js"></script>
<script src="vendor/magnific-popup/jquery.magnific-popup.min.js"></script>
<!-- Custom scripts for this template -->
<script src="js/creative.min.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Smart Working Environment Monitoring Service</title>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<link href="https://fonts.googleapis.com/css?family=Raleway:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
<link href="css/abc.css" rel="stylesheet">
<!-- Bootstrap core CSS -->
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Plugin CSS -->
<link href="vendor/magnific-popup/magnific-popup.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="css/creative.min.css" rel="stylesheet">
<!-- jquery -->
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<!-- 모비우스 -->
<script src="./mobi-hero-mobius.js"></script>
<script>
// <ae>worker 생성 시, 모든 cnt, grp 자동 생성하고 cnt 중 name과 hp는 cin까지 등록해줌
function createWorker(workerId, name, hp){
console.log("<ae>worker register : " + workerId +' ' + name + ' ' + ' ' + hp);
let uri = path;
let item = {
"m2m:ae" : {
"rn": workerId,
"api": 'worker',
"rr": true
}
}
fetch(uri, {
method: 'POST',
headers: {
//'Host':'<calculated when request is sent>',
//'User-Agent':'PostmanRuntime/7.28.4',
//'Accept': 'application/json',
//'Accept-Encoding':'gzip, deflate, br',
//'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':workerId,
'Content-Type': 'application/json;ty=2',
'Content-Length':'100'
},
body: JSON.stringify(item)
})
.then((res) => {
if (res.statusText == 'OK' || res.statusText == 'Created') {
res.json().then(data => {
createCnt(workerId, 'name', 100, name);
createCnt(workerId, 'hp', 100, hp);
createCnt(workerId, 'location', 100, 'En');
createCnt(workerId, 'heartrate', 100);
createCnt(workerId, 'danger', 100, 0);
createCnt(workerId, 'temperature', 100, 0);
createCnt(workerId, 'humidity', 100, 0);
createCnt(workerId, 'methane', 100, 0);
createCnt(workerId, 'cmonoxide', 100, 0);
createCnt(workerId, 'buzzer', 100, "OFF");
createGrp(workerId, mode = 'biogrp');
createGrp(workerId, mode = 'entgrp');
createGrp(workerId, mode = 'notegrp');
});
alert("Registered.");
$('#userid').val('');
$('#username').val('');
$('#userphone').val('');
}
else {
alert('Error');
console.error(res);
}
}).catch(err => console.error(err));
}
</script>
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
<div class="container">
<a class="navbar-brand js-scroll-trigger" href="index.html">Home</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="registration.html">Worker Registration</a>
</li>
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="users.html">Worker Inquire</a>
</li>
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="zone-monitoring.html">Zone Moniroting</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<header>
<h1></h1> <br>
</header>
<section>
<div id="container_demo">
<a class="hiddenanchor" id="tologin"></a>
<div id="wrapper">
<div id="login" class="animate form">
<form action="#" target="iframe1">
<h1>Worker Registration</h1>
<p>
<label for="userid" class="userid"> ID </label>
<input id="userid" name="userid" type="text" />
</p>
<p>
<label for="username" class="username"> Name </label>
<input id="username" name="username" type="text" />
</p>
<p>
<label for="userphone" class="userphone"> H.P </label>
<input id="userphone" name="userphone" type="userphone" />
</p>
<p class="signin button">
<input type="button" name="submit" value="Input" onclick="createWorker($('#userid').val(), $('#username').val(), $('#userphone').val())"/>
</p>
<p class="change_link">
<a href="index.html">Back</a>
</p>
</form>
<iframe name="iframe1" style="display:none"></iframe> <!-- 페이지 이동 방지 -->
</div>
</div>
</div>
</section>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Smart Working Environment Monitoring Service</title>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<link href="https://fonts.googleapis.com/css?family=Raleway:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
<link href="css/abc.css" rel="stylesheet">
<!-- Bootstrap core CSS -->
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Plugin CSS -->
<link href="vendor/magnific-popup/magnific-popup.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="css/creative.min.css" rel="stylesheet">
<!-- jquery -->
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<!-- 모비우스 -->
<script src="./mobi-hero-mobius.js"></script>
<style>
table {
border-collapse: collapse;
width: auto;
}
th,
td {
text-align: left;
padding: 3px;
}
tr:nth-child(even) {
background-color: #f2f2f2
}
th {
background-color: #4CAF50;
color: white;
}
</style>
<script>
$(document).ready(function () {
selectWorker();
});
function selectWorker(){
console.log("worker Inquire : ");
let uri = path + '?rcn=4&ty=2';
fetch(uri, {
method: 'GET',
headers: {
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':'admin',
'Content-Type': 'application/json'
}
})
.then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
console.log(data);
$("#worker_table > tbody > tr").remove();
let list = data['m2m:rsp']['m2m:ae'];
let idx = 0;
for(let i=0; i<list.length; i++){
if(list[i]['api'] == 'worker'){
console.log(list[i]['rn']);
let table = $("#worker_table");
selectGrpAsync(list[i]['rn'], 'notegrp').then((res) => {
if (res.statusText == 'OK' || res.statusText == 'Created') {
res.json().then(data => {
idx +=1;
let name = data["m2m:agr"]["m2m:rsp"][0]["pc"]["m2m:cin"]["con"]; // 이름
let hp = data["m2m:agr"]["m2m:rsp"][1]["pc"]["m2m:cin"]["con"]; // 전화번호
let loc = data["m2m:agr"]["m2m:rsp"][2]["pc"]["m2m:cin"]["con"]; // 출근 상태
loc = loc=='En' ? '-' : 'On';
let row = "<tr>"
+ "<td>" + idx + "</td>"
+ "<td>" + list[i]['rn'] + "</td>"
+ "<td>" + name + "</td>"
+ "<td>" + hp + "</td>"
+ "<td>" + loc + "</td>"
//+ "<td><a href='list.html' onclick='clickListPage(this)'>조회</a></td>"
//+ "<td><a href='monitoring.html' onclick='clickMonitoringPage(this)'>모니터링</a></td>"
//+ "<td><a href='' onclick='clickDeleteWorker(this)'>삭제</a></td>"
+ "<td><button type='button' class='btn btn-dark btn-sm' onclick='clickListPage(this)'>Inquire</button></td>"
+ "<td><button type='button' class='btn btn-info btn-sm' onclick='clickMonitoringPage(this)'>Monitoring</button></td>"
+ "<td><button type='button' class='btn btn-primary btn-sm' onclick='clickDeleteWorker(this)'>Delete</button></td>"
+ "</tr>";
table.append(row);
});
}
else {
alert('Error');
console.error(res);
}
}).catch(err => console.error(err));
}
}
});
}
else {
alert('Error');
console.error(res);
}
}).catch(err => console.error(err));
}
// 작업자조회 > 조회 버튼 클릭 이벤트
function clickListPage(id){
let ae_resource = $(id).closest('tr').find("td:eq(1)").text();
localStorage.setItem('list_item', ae_resource);
location.href='list.html';
}
// 작업자조회 > 모니터링 버튼 클릭 이벤트
function clickMonitoringPage(id){
let ae_resource = $(id).closest('tr').find("td:eq(1)").text();
let name = $(id).closest('tr').find("td:eq(2)").text();
localStorage.setItem('list_item', ae_resource);
localStorage.setItem('list_item2', name);
location.href='monitoring.html';
}
// 작업자조회 > 삭제 버튼 클릭 이벤트
function clickDeleteWorker(id){
let ae_resource = $(id).closest('tr').find("td:eq(1)").text();
let res = confirm("Worker '" + ae_resource + "' Delete?");
if(res){
deleteAe(ae_resource);
}
}
</script>
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
<div class="container">
<a class="navbar-brand js-scroll-trigger" href="index.html">Home</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="registration.html">Worker Registration</a>
</li>
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="users.html">Worker Inquire</a>
</li>
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="zone-monitoring.html">Zone Moniroting</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<header>
<h1></h1> <br><br><br>
</header>
<section>
<div id="container_demo">
<a class="hiddenanchor" id="toadmin_users"></a>
<div id="wrapper2">
<div id="login" class="animate form">
<form>
<h1>Worker Inquire</h1>
<table border="2" align="center" id="worker_table">
<thead>
<tr bgcolor="yellow" align="center">
<th> No </th>
<th> ID </th>
<th> Name </th>
<th> H.P </th>
<th> Go To Work </th>
<th> Inquire </th>
<th> Monitoring </th>
<th> Delete </th>
</tr>
</thead>
<tbody>
</tbody>
</table> <br><br>
<p class="change_link2">
<a href="index.html">Back</a>
</p>
</form>
</div>
</div>
</div>
</section>
</div>
</body>
</html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Smart Working Environment Monitoring Service</title>
<!-- Bootstrap core CSS -->
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom fonts for this template -->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Merriweather:400,300,300italic,400italic,700,700italic,900,900italic' rel='stylesheet' type='text/css'>
<!-- Plugin CSS -->
<link href="vendor/magnific-popup/magnific-popup.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="css/creative.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<link href="https://fonts.googleapis.com/css?family=Raleway:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
<link href="css/abc.css" rel="stylesheet">
<!-- jquery -->
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<!-- 모비우스 -->
<script src="./mobi-hero-mobius.js"></script>
<!-- 아이콘 -->
<script src="https://use.fontawesome.com/releases/v5.2.0/js/all.js"></script>
<style>
.box{
display: flex;
height: 150px;
width: 300px;
justify-content: center;
align-items: center;
border: solid 1px gray;
font-size:xx-large;
font-weight: bold;
}
</style>
<script>
let name = hp = loc = danger = '';
$(document).ready(function () {
// 페이지 이동 시 넘어오는 ae_resource 값
if(localStorage.getItem('list_item')){
let ae_resource = localStorage.getItem('list_item');
console.log(ae_resource);
// notegrp 값 가져옴
selectGrpAsync(ae_resource, 'notegrp').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
// console.log("notegrp 응답");
// console.log(data['m2m:agr']['m2m:rsp'][0]['pc']['m2m:cin']['con']); // 이름
// console.log(data['m2m:agr']['m2m:rsp'][1]['pc']['m2m:cin']['con']); // 전화번호
try{
name = data['m2m:agr']['m2m:rsp'][0]['pc']['m2m:cin']['con'];
hp = data['m2m:agr']['m2m:rsp'][1]['pc']['m2m:cin']['con'];
} catch{
console.log("notegrp catch!");
}
// 여기에 notegrp 값 활용 코드 작업
$('#item1').text(ae_resource);
$('#item2').text(name);
$('#item3').text(hp);
});
}
}).catch(err => console.error(err));
// biogrp 값 가져옴
selectGrpAsync(ae_resource, 'biogrp').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
try{
loc = data['m2m:agr']['m2m:rsp'][0]['pc']['m2m:cin']['con'];
$("#box1").text(loc);
}catch{
console.log("biogrp catch!");
$("#box1").text('');
$("#box1").append('<i class="fas fa-exclamation-triangle"></i>')
}
try{
danger = data['m2m:agr']['m2m:rsp'][2]['pc']['m2m:cin']['con'];
if(danger == '0'){
$("#box2").text("NORMAL");
$("#box2").css("color","green");
}
else{
$("#box2").text("FALL DOWN");
$("#box2").css("color","red");
}
}catch{
console.log("biogrp catch!");
$("#box2").text('');
$("#box2").append('<i class="fas fa-exclamation-triangle"></i>');
}
});
}
}).catch(err => console.error(err));
}
});
</script>
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
<div class="container">
<a class="navbar-brand js-scroll-trigger" href="index.html">Home</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="registration.html">Worker Registration</a>
</li>
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="users.html">Worker Inquire</a>
</li>
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="zone-monitoring.html">Zone Moniroting</a>
</li>
</ul>
</div>
</div>
</nav>
<section>
<div class="container">
<div id="container_demo">
<a class="hiddenanchor" id="toadmin_users"></a>
<div id="wrapper2">
<div id="login" class="animate form">
<form>
<h1>Worker Information</h1>
<table>
<tr>
<td><b> ID </b></td>
<td style="padding: 0px 10px;"><b>:</b></td>
<td><span id="item1"></span></td>
</tr>
<tr>
<td><b> Name </b></td>
<td style="padding: 0px 10px;"><b>:</b></td>
<td><span id="item2"></span></td>
</tr>
<tr>
<td><b> H.P </b></td>
<td style="padding: 0px 10px;"><b>:</b></td>
<td><span id="item3"></span></td>
</tr>
</table>
<br>
<table style="width: 100%;">
<tr>
<th><b> Location </b></th>
<th><b> Fall Down </b></th>
</tr>
<tr>
<td> <div class="box" id="box1"></div> </td>
<td> <div class="box" id="box2"></div> </td>
</tr>
</table>
<br>
<i class="exclamation-circle"></i>
<br><br>
<p class="change_link2">
<a href="users.html">Back</a>
</p>
</form>
</div>
</div>
</div>
</section>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Smart Working Environment Monitoring Service</title>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<link href="https://fonts.googleapis.com/css?family=Raleway:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
<link href="css/abc.css" rel="stylesheet">
<!-- Bootstrap core CSS -->
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Plugin CSS -->
<link href="vendor/magnific-popup/magnific-popup.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="css/creative.min.css" rel="stylesheet">
<!-- jquery -->
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<!-- 모비우스 -->
<script src="./mobi-hero-mobius.js"></script>
<!-- 아이콘 -->
<script src="https://use.fontawesome.com/releases/v5.2.0/js/all.js"></script>
<!-- 차트 -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<style>
.box{
display: flex;
height: 150px;
width: 220px;
justify-content: center;
align-items: center;
border: solid 1px gray;
font-size:xx-large;
font-weight: bold;
}
#notiCard{
position: fixed;
bottom: 10px;
right: 10px;
padding: 5px;
font-size: small;
text-align: left;
}
.card-body{
padding: 10px;
}
.card-header{
padding: 5px;
}
#notiTable{
width: 300px;
}
</style>
<script>
let ae_resource;
let name;
$(document).ready(function () {
if(localStorage.getItem('list_item')){
ae_resource = localStorage.getItem('list_item');
name = localStorage.getItem('list_item2');
$('#worker').text(name+' ('+ae_resource+')');
getBioData();
startGetBioData();
// 온도 그래프 그림
drawTempChart(ae_resource);
// 습도 그래프 그림
drawHumiChart(ae_resource);
// 메탄가스 그래프 그림
drawMethChart(ae_resource);
// 일산화탄소 그래프 그림
drawCmonChart(ae_resource);
}
});
startGetBioData = function() {
playAlert = setInterval(function() {
getBioData();
}, 5000);
};
function getBioData(){
// biogrp 조회
selectGrpAsync(ae_resource, 'biogrp').then((res) => {
if (res.statusText == 'OK') {
let loc = heart = danger = '';
res.json().then(data => {
try{
loc = data['m2m:agr']['m2m:rsp'][0]['pc']['m2m:cin']['con'];
$("#box1").text(loc);
}catch{
console.log("biogrp > loc catch!");
$("#box1").text('');
$("#box1").append('<i class="fas fa-exclamation-triangle"></i>');
}
try{
heart = data['m2m:agr']['m2m:rsp'][1]['pc']['m2m:cin']['con'];
if ($("#box2").text() != heart){
if(heart < 65){
$('#td1').text("Worker heart rate is dangerous.");
}
else{
$('#td1').text('');
}
}
$("#box2").text(heart);
}catch{
console.log("biogrp > heart catch!");
$("#box2").text('');
$("#box2").append('<i class="fas fa-exclamation-triangle"></i>');
$('#td1').text('');
}
try{
danger = data['m2m:agr']['m2m:rsp'][2]['pc']['m2m:cin']['con'];
console.log("danger?");
console.log(danger);
if(danger == '0'){
$("#box3").text("NORMAL");
$("#box3").css("color","green");
$('#td2').text('');
}
else{
if($("#box3").text() != "FALL DOWN"){
$('#td2').text("A fall of the worker has been detected.");
}
$("#box3").text("FALL DOWN");
$("#box3").css("color","red");
}
}catch{
console.log("biogrp > heart catch!");
$("#box3").text('');
$("#box3").append('<i class="fas fa-exclamation-triangle"></i>');
$('#td2').text('');
}
checkNoti();
});
}
else {
alert('ERROR');
console.error(res);
}
}).catch(err => console.error(err));
}
// 알림 버튼 클릭 이벤트
function clickAlertPage(){
localStorage.setItem('list_item', ae_resource);
location.href='alert.html';
}
function closeNoti(){
$('#td1').text('');
$('#td2').text('');
$('#td3').text('');
$('#td4').text('');
$('#td5').text('');
$('#td6').text('');
$('#notiCard').hide();
}
function openNoti(){
$('#notiCard').show();
}
function checkNoti(){
if($('#td1').text() == '' && $('#td2').text() == '' && $('#td3').text() == '' && $('#td4').text() == '' && $('#td5').text() == '' && $('#td6').text() == ''){
$('#notiCard').hide();
}
else{
$('#notiCard').show();
}
}
</script>
</head>
<body id="page-top">
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
<div class="container">
<a class="navbar-brand js-scroll-trigger" href="index.html">Home</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="registration.html">Worker Registration</a>
</li>
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="users.html">Worker Inquire</a>
</li>
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="zone-monitoring.html">Zone Moniroting</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<section>
<div id="container_demo">
<a class="hiddenanchor" id="toadmin_users"></a>
<div id="wrapper2">
<div id="login" class="animate form">
<form>
<h1>Monitoring</h1>
<div>
<h2 id="worker"> </h2>
</div>
<br>
<div>
<table border="0" align="center">
<tr align="left" style="width: 100%;">
<th style="width: 30%; padding-right: 10px;"> <b>Location</b> </th>
<th style="width: 30%; padding-right: 10px"> <b>Heart Rate</b> </th>
<th style="width: 30%;"> <b>Fall Down</b> </th>
</tr>
<tr align="left" style="width: 100%;">
<td> <div class="box" id="box1"></div> </td>
<td> <div class="box" id="box2"></div> </td>
<td> <div class="box" id="box3"></div> </td>
</tr>
</table>
</div>
<br>
<br>
<!--온도 그래프-->
<div class="chart-container" style="position: relative; height:300px; width:100%;">
<canvas id="tempChart"></canvas>
</div>
<br>
<!--습도 그래프-->
<div class="chart-container" style="position: relative; height:300px; width:100%;">
<canvas id="humiChart"></canvas>
</div>
<br>
<!--메탄가스 그래프-->
<div class="chart-container" style="position: relative; height:300px; width:100%;">
<canvas id="methChart"></canvas>
</div>
<br>
<!--일산화탄소 그래프-->
<div class="chart-container" style="position: relative; height:300px; width:100%;">
<canvas id="cmonChart"></canvas>
</div>
<br>
<br><br>
<p class="change_link2">
<a href="users.html">Back</a>
</p>
</form>
</div>
</div>
</div>
</section>
<div class="card" id="notiCard">
<div class="card-header">
<button type="button" class="close" onclick="closeNoti()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="card-body">
<table id="notiTable">
<tbody>
<tr>
<td id="td1"></td>
</tr>
<tr>
<td id="td2"></td>
</tr>
<tr>
<td id="td3"></td>
</tr>
<tr>
<td id="td4"></td>
</tr>
<tr>
<td id="td5"></td>
</tr>
<tr>
<td id="td6"></td>
</tr>
<tr style="text-align: right;">
<td><button type='button' class='btn btn-primary btn-sm' onclick='clickAlert()'>알림</button></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
function clickAlert(){
$('#td1').text('');
$('#td2').text('');
$('#td3').text('');
$('#td4').text('');
$('#td5').text('');
$('#td6').text('');
$('#notiCard').hide();
createCin(ae_resource, 'buzzer', 'ON');
}
</script>
<!-- 온도 그래프 관련 스크립트 -->
<script>
startCheckTempChart = function() {
playAlert = setInterval(function() {
checkTempChart(ae_resource);
}, 5000);
};
let tempConfig;
let tempCtx;
let tempChart;
let lastTemp = 0;
function drawTempChart(ae_resource){
selectCinAsync(ae_resource, 'temperature').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let list = data['m2m:rsp']['m2m:cin'];
lastTemp = list[0]['ct']; // 온도 데이터 마지막 timestamp 값 저장
let timeArr = [];
let conArr = [];
// 주의) 모비우스에 새로운 데이터가 앞에서부터 추가됨.
let lastIdx = list.length > 15 ? 16 : list.length;
for(let i=0; i<lastIdx; i++){
let date = list[i]['ct'].substr(2,2)+'-'+list[i]['ct'].substr(4,2)+'-'+list[i]['ct'].substr(6,2)+' '+list[i]['ct'].substr(9,2)+':'+list[i]['ct'].substr(11,2)+':'+list[i]['ct'].substr(13,2);
// 최신데이터가 앞에있어서 배열에 앞에서부터 추가하면 제대로 정렬됨
timeArr.unshift(date);
conArr.unshift(list[i]['con']);
}
tempCtx = document.getElementById('tempChart');
tempConfig = {
type: 'line',
data: {
labels: timeArr,
datasets: [{
label: 'temp',
backgroundColor: 'rgba(255, 99, 132, 1)',
borderColor: 'rgba(255, 99, 132, 0.8)',
fill: false,
data: conArr,
}]
},
options: {
maintainAspectRatio: false,
legend: {
display: false
},
title: {
display : true, text: 'Temp Graph'
},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: 'Temp'
}
}]
},
}
};
//차트 그리기
tempChart = new Chart(tempCtx, tempConfig);
startCheckTempChart();
});
}
}).catch(err => console.error(err));
}
// 데이터 select해서 그래프에 그려지지 않은 데이터 있으면 추가
function checkTempChart(ae_resource){
selectCinAsync(ae_resource, 'temperature').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let list = data['m2m:rsp']['m2m:cin'];
if(list[0]['ct'] != lastTemp){
lastTemp = list[0]['ct'];
let date = list[0]['ct'].substr(2,2)+'-'+list[0]['ct'].substr(4,2)+'-'+list[0]['ct'].substr(6,2)+' '+list[0]['ct'].substr(9,2)+':'+list[0]['ct'].substr(11,2)+':'+list[0]['ct'].substr(13,2);
insertTempChart(tempConfig, date, list[0]['con']);
if(list[0]['con'] > 49){
$('#td3').text("Worker temperature is dangerous.");
checkNoti();
}
else{
$('#td3').text('');
checkNoti();
}
}
});
}
}).catch(err => console.error(err));
}
function insertTempChart(tempConfig, label, data){
tempConfig.data.labels.push(label);
var dataset = tempConfig.data.datasets;
dataset[0].data.push(data);
// x축 15개 고정하기 위함
if(tempConfig.data.labels.length > 15){
tempConfig.data.labels.shift();
dataset[0].data.shift();
}
tempChart.update(); //차트 업데이트
}
</script>
<!-- 습도 그래프 관련 스크립트 -->
<script>
startCheckHumiChart = function() {
playAlert = setInterval(function() {
checkHumiChart(ae_resource);
}, 5000);
};
let humiConfig;
let humiCtx;
let humiChart;
let lastHumi = 0;
function drawHumiChart(ae_resource){
selectCinAsync(ae_resource, 'humidity').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let list = data['m2m:rsp']['m2m:cin'];
lastHumi = list[0]['ct']; // 습도 데이터 마지막 timestamp 값 저장
let timeArr = [];
let conArr = [];
// 주의) 모비우스에 새로운 데이터가 앞에서부터 추가됨.
let lastIdx = list.length > 15 ? 16 : list.length;
for(let i=0; i<lastIdx; i++){
let date = list[i]['ct'].substr(2,2)+'-'+list[i]['ct'].substr(4,2)+'-'+list[i]['ct'].substr(6,2)+' '+list[i]['ct'].substr(9,2)+':'+list[i]['ct'].substr(11,2)+':'+list[i]['ct'].substr(13,2);
// 최신데이터가 앞에있어서 배열에 앞에서부터 추가하면 제대로 정렬됨
timeArr.unshift(date);
conArr.unshift(list[i]['con']);
}
humiCtx = document.getElementById('humiChart');
humiConfig = {
type: 'line',
data: {
labels: timeArr,
datasets: [{
label: 'humi',
backgroundColor: 'rgba(54, 162, 235, 1)',
borderColor: 'rgba(54, 162, 235, 0.8)',
fill: false,
data: conArr,
}]
},
options: {
maintainAspectRatio: false,
legend: {
display: false
},
title: {
display : true, text: 'Humidity Graph'
},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: 'Humidity'
}
}]
},
}
};
//차트 그리기
humiChart = new Chart(humiCtx, humiConfig);
startCheckHumiChart();
});
}
}).catch(err => console.error(err));
}
// 데이터 select해서 그래프에 그려지지 않은 데이터 있으면 추가
function checkHumiChart(ae_resource){
selectCinAsync(ae_resource, 'humidity').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let list = data['m2m:rsp']['m2m:cin'];
if(list[0]['ct'] != lastHumi){
lastHumi = list[0]['ct'];
let date = list[0]['ct'].substr(2,2)+'-'+list[0]['ct'].substr(4,2)+'-'+list[0]['ct'].substr(6,2)+' '+list[0]['ct'].substr(9,2)+':'+list[0]['ct'].substr(11,2)+':'+list[0]['ct'].substr(13,2);
insertHumiChart(humiConfig, date, list[0]['con']);
if(list[0]['con'] > 69){
$('#td4').text("Worker humidity is dangerous.");
checkNoti();
}
else{
$('#td4').text('');
checkNoti();
}
}
});
}
}).catch(err => console.error(err));
}
function insertHumiChart(humiConfig, label, data){
humiConfig.data.labels.push(label);
var dataset = humiConfig.data.datasets;
dataset[0].data.push(data);
// x축 15개 고정하기 위함
if(humiConfig.data.labels.length > 15){
humiConfig.data.labels.shift();
dataset[0].data.shift();
}
humiChart.update(); //차트 업데이트
}
</script>
<!-- 메탄가스 그래프 관련 스크립트 -->
<script>
startCheckMethChart = function() {
playAlert = setInterval(function() {
checkMethChart(ae_resource);
}, 5000);
};
let methConfig;
let methCtx;
let methChart;
let lastMeth = 0;
function drawMethChart(ae_resource){
selectCinAsync(ae_resource, 'methane').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let list = data['m2m:rsp']['m2m:cin'];
lastMeth = list[0]['ct'];
let timeArr = [];
let conArr = [];
// 주의) 모비우스에 새로운 데이터가 앞에서부터 추가됨.
let lastIdx = list.length > 15 ? 16 : list.length;
for(let i=0; i<lastIdx; i++){
let date = list[i]['ct'].substr(2,2)+'-'+list[i]['ct'].substr(4,2)+'-'+list[i]['ct'].substr(6,2)+' '+list[i]['ct'].substr(9,2)+':'+list[i]['ct'].substr(11,2)+':'+list[i]['ct'].substr(13,2);
// 최신데이터가 앞에있어서 배열에 앞에서부터 추가하면 제대로 정렬됨
timeArr.unshift(date);
conArr.unshift(list[i]['con']);
}
methCtx = document.getElementById('methChart');
methConfig = {
type: 'line',
data: {
labels: timeArr,
datasets: [{
label: 'meth',
backgroundColor: 'rgba(255, 206, 86, 1)',
borderColor: 'rgba(255, 206, 86, 0.8)',
fill: false,
data: conArr,
}]
},
options: {
maintainAspectRatio: false,
legend: {
display: false
},
title: {
display : true, text: 'Methane Graph'
},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: 'Methane gas'
}
}]
},
}
};
//차트 그리기
methChart = new Chart(methCtx, methConfig);
startCheckMethChart();
});
}
}).catch(err => console.error(err));
}
// 데이터 select해서 그래프에 그려지지 않은 데이터 있으면 추가
function checkMethChart(ae_resource){
selectCinAsync(ae_resource, 'methane').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let list = data['m2m:rsp']['m2m:cin'];
if(list[0]['ct'] != lastMeth){
lastMeth = list[0]['ct'];
let date = list[0]['ct'].substr(2,2)+'-'+list[0]['ct'].substr(4,2)+'-'+list[0]['ct'].substr(6,2)+' '+list[0]['ct'].substr(9,2)+':'+list[0]['ct'].substr(11,2)+':'+list[0]['ct'].substr(13,2);
insertMethChart(methConfig, date, list[0]['con']);
if(list[0]['con'] > 49){
$('#td5').text("Worker mehtane gas is dangerous.");
checkNoti();
}
else{
$('#td5').text('');
checkNoti();
}
}
});
}
}).catch(err => console.error(err));
}
function insertMethChart(methConfig, label, data){
methConfig.data.labels.push(label);
var dataset = methConfig.data.datasets;
dataset[0].data.push(data);
// x축 15개 고정하기 위함
if(methConfig.data.labels.length > 15){
methConfig.data.labels.shift();
dataset[0].data.shift();
}
methChart.update(); //차트 업데이트
}
</script>
<!-- 일산화탄소 그래프 관련 스크립트 -->
<script>
startCheckCmonChart = function() {
playAlert = setInterval(function() {
checkCmonChart(ae_resource);
}, 5000);
};
let cmonConfig;
let cmonCtx;
let cmonChart;
let lastCmon = 0;
function drawCmonChart(ae_resource){
selectCinAsync(ae_resource, 'cmonoxide').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let list = data['m2m:rsp']['m2m:cin'];
lastCmon = list[0]['ct'];
let timeArr = [];
let conArr = [];
// 주의) 모비우스에 새로운 데이터가 앞에서부터 추가됨.
let lastIdx = list.length > 15 ? 16 : list.length;
for(let i=0; i<lastIdx; i++){
let date = list[i]['ct'].substr(2,2)+'-'+list[i]['ct'].substr(4,2)+'-'+list[i]['ct'].substr(6,2)+' '+list[i]['ct'].substr(9,2)+':'+list[i]['ct'].substr(11,2)+':'+list[i]['ct'].substr(13,2);
// 최신데이터가 앞에있어서 배열에 앞에서부터 추가하면 제대로 정렬됨
timeArr.unshift(date);
conArr.unshift(list[i]['con']);
}
cmonCtx = document.getElementById('cmonChart');
cmonConfig = {
type: 'line',
data: {
labels: timeArr,
datasets: [{
label: 'cmon',
backgroundColor: 'rgba(75, 192, 192, 1)',
borderColor: 'rgba(75, 192, 192, 0.8)',
fill: false,
data: conArr,
}]
},
options: {
maintainAspectRatio: false,
legend: {
display: false
},
title: {
display : true, text: 'Cmonoxide Graph'
},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: 'Cmonoxide'
}
}]
},
}
};
//차트 그리기
cmonChart = new Chart(cmonCtx, cmonConfig);
startCheckCmonChart();
});
}
}).catch(err => console.error(err));
}
// 데이터 select해서 그래프에 그려지지 않은 데이터 있으면 추가
function checkCmonChart(ae_resource){
selectCinAsync(ae_resource, 'cmonoxide').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let list = data['m2m:rsp']['m2m:cin'];
if(list[0]['ct'] != lastCmon){
lastCmon = list[0]['ct'];
let date = list[0]['ct'].substr(2,2)+'-'+list[0]['ct'].substr(4,2)+'-'+list[0]['ct'].substr(6,2)+' '+list[0]['ct'].substr(9,2)+':'+list[0]['ct'].substr(11,2)+':'+list[0]['ct'].substr(13,2);
insertCmonChart(cmonConfig, date, list[0]['con']);
if(list[0]['con'] > 49){
$('#td6').text("Worker cmonoxide is dangerous..");
checkNoti();
}
else{
$('#td6').text('');
checkNoti();
}
}
});
}
}).catch(err => console.error(err));
}
function insertCmonChart(cmonConfig, label, data){
cmonConfig.data.labels.push(label);
var dataset = cmonConfig.data.datasets;
dataset[0].data.push(data);
// x축 15개 고정하기 위함
if(cmonConfig.data.labels.length > 15){
cmonConfig.data.labels.shift();
dataset[0].data.shift();
}
cmonChart.update(); //차트 업데이트
}
</script>
</body>
<!-- Bootstrap core JavaScript -->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Plugin JavaScript -->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<script src="vendor/scrollreveal/scrollreveal.min.js"></script>
<script src="vendor/magnific-popup/jquery.magnific-popup.min.js"></script>
<!-- Custom scripts for this template -->
<script src="js/creative.min.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Smart Working Environment Monitoring Service</title>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<link href="https://fonts.googleapis.com/css?family=Raleway:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
<link href="css/abc.css" rel="stylesheet">
<!-- Bootstrap core CSS -->
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Plugin CSS -->
<link href="vendor/magnific-popup/magnific-popup.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="css/creative.min.css" rel="stylesheet">
<!-- jquery -->
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<!-- 모비우스 -->
<script src="./mobi-hero-mobius.js"></script>
<!-- 아이콘 -->
<script src="https://use.fontawesome.com/releases/v5.2.0/js/all.js"></script>
<!-- 차트 -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<style>
.box{
display: flex;
height: 150px;
width: 220px;
justify-content: center;
align-items: center;
border: solid 1px gray;
font-size:xx-large;
font-weight: bold;
}
.placeBox{
border: 1px solid black;
width: 100%;
height: 100px;
margin-bottom: 20px;
padding: 10px;
}
#notiCard{
position: fixed;
bottom: 10px;
right: 10px;
padding: 5px;
font-size: small;
text-align: left;
}
.card-body{
padding: 10px;
}
.card-header{
padding: 5px;
}
#notiTable{
width: 300px;
}
</style>
</head>
<body id="page-top">
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
<div class="container">
<a class="navbar-brand js-scroll-trigger" href="index.html">Home</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="registration.html">Worker Registration</a>
</li>
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="users.html">Worker Inquire</a>
</li>
<li class="nav-item">
<a class="nav-link js-scroll-trigger" href="zone-monitoring.html">Zone Moniroting</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<section>
<div id="container_demo">
<a class="hiddenanchor" id="toadmin_users"></a>
<div id="wrapper2">
<div id="login" class="animate form">
<form>
<h1>Zone Monitoring</h1>
<img src="./img/drawing.png" width="100%" alt="" style="margin-bottom: 10px;">
<div class="placeBox">
<label style="font-weight: bolder;">A1</label>
<label style="float: right">Number of people : <label id="total_a1">0</label></label>
<br><br>
<p id="list_a1"></p>
</div>
<div class="placeBox">
<label style="font-weight: bolder;">A2</label>
<label style="float: right">Number of people : <label id="total_a2">0</label></label>
<br><br>
<p id="list_a2"></p>
</div>
<div class="placeBox">
<label style="font-weight: bolder;">A3</label>
<label style="float: right">Number of people : <label id="total_a3">0</label></label>
<br><br>
<p id="list_a3"></p>
</div>
<div class="placeBox">
<label style="font-weight: bolder;">A4</label>
<label style="float: right">Number of people : <label id="total_a4">0</label></label>
<br><br>
<p id="list_a4"></p>
</div>
<br>
<!--온도 그래프-->
<div class="chart-container" style="position: relative; height:300px; width:100%; margin-bottom: 50px;">
<canvas id="tempChart"></canvas>
</div>
<br>
<br>
<br>
<!--습도 그래프-->
<div class="chart-container" style="position: relative; height:300px; width:100%; margin-bottom: 50px;">
<canvas id="humiChart"></canvas>
</div>
<br>
<br>
<br>
<!--메탄가스 그래프-->
<div class="chart-container" style="position: relative; height:300px; width:100%; margin-bottom: 50px;">
<canvas id="methChart"></canvas>
</div>
<br>
<br>
<br>
<!--일산화탄소 그래프-->
<div class="chart-container" style="position: relative; height:300px; width:100%; margin-bottom: 50px;">
<canvas id="cmonChart"></canvas>
</div>
<br>
<br><br>
<p class="change_link2">
<a href="index.html">Back</a>
</p>
</form>
</div>
</div>
</div>
</section>
<div class="card" id="notiCard">
<div class="card-header">
<button type="button" class="close" onclick="closeNoti()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="card-body">
<table id="notiTable">
<tbody>
<tr>
<td id="td1"></td>
</tr>
<tr>
<td id="td2"></td>
</tr>
<tr>
<td id="td3"></td>
</tr>
<tr>
<td id="td4"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
function closeNoti(){
$('#notiCard').hide();
}
function openNoti(){
$('#notiCard').show();
}
let ae_resource;
let name;
$(document).ready(function () {
$('#notiCard').hide();
displayZoneList();
startDisplayZoneList();
// 온도 그래프 그림
drawZoneTempChart();
// 습도 그래프 그림
drawZoneHumiChart();
// 메탄가스 그래프 그림
drawZoneMethChart();
// 일산화탄소 그래프 그림
drawZoneCmonChart();
});
startDisplayZoneList = function() {
playAlert = setInterval(function() {
displayZoneList();
}, 5000);
};
function displayZoneList(){
console.log("worker list : ");
let uri = path + '?rcn=4&ty=2';
fetch(uri, {
method: 'GET',
headers: {
'Host':'<calculated when request is sent>',
'User-Agent':'PostmanRuntime/7.28.4',
'Accept': 'application/json',
'Accept-Encoding':'gzip, deflate, br',
'Connection':'keep-alive',
'X-M2M-RI':'12345',
'X-M2M-Origin':'admin',
'Content-Type': 'application/json'
}
})
.then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let list = data['m2m:rsp']['m2m:ae'];
let a1_str = "";
let a2_str = "";
let a3_str = "";
let a4_str = "";
let a1_num = 0;
let a2_num = 0;
let a3_num = 0;
let a4_num = 0;
for(let i=0; i<list.length; i++){
if(list[i]['api'] == 'worker'){
selectGrpAsync(list[i]['rn'], 'notegrp').then((res) => {
if (res.statusText == 'OK' || res.statusText == 'Created') {
res.json().then(data => {
let name = data["m2m:agr"]["m2m:rsp"][0]["pc"]["m2m:cin"]["con"]; // 이름
let hp = data["m2m:agr"]["m2m:rsp"][1]["pc"]["m2m:cin"]["con"]; // 전화번호
let loc = data["m2m:agr"]["m2m:rsp"][2]["pc"]["m2m:cin"]["con"]; // 출근 상태
console.log(list[i]['rn'] + ' : ' +name + ' ' + hp + ' ' + loc);
if(loc == 'A1'){
a1_num++;
a1_str = a1_str + name + ' ';
}
else if(loc == 'A2'){
a2_num++;
a2_str = a2_str + name + ' ';
}
else if(loc == 'A3'){
a3_num++;
a3_str = a3_str + name + ' ';
}
else if(loc == 'A4'){
a4_num++;
a4_str = a4_str + name + ' ';
}
else{
}
// 구역별 인원 목록 작성
$('#total_a1').text(a1_num);
$('#list_a1').text(a1_str);
$('#total_a2').text(a2_num);
$('#list_a2').text(a2_str);
$('#total_a3').text(a3_num);
$('#list_a3').text(a3_str);
$('#total_a4').text(a4_num);
$('#list_a4').text(a4_str);
});
}
else {
alert('ERROR');
console.error(res);
}
}).catch(err => console.error(err));
}
}
});
}
else {
alert('ERROR');
console.error(res);
}
}).catch(err => console.error(err));
}
</script>
<!-- 구역별 온도 그래프 관련 -->
<script>
let tList = [];
let tempConfig;
let tempCtx;
let tempChart;
startZoneCheckTempChart = function() {
playAlert = setInterval(function() {
checkZoneTempChart();
}, 5000);
};
function drawZoneTempChart(){
selectGrpAsync('Zone', 'ztempgrp').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
tList.push(data['m2m:agr']['m2m:rsp'][0]['pc']['m2m:cin']['con']); // A1 구역 온도 값
tList.push(data['m2m:agr']['m2m:rsp'][1]['pc']['m2m:cin']['con']); // A2 구역 온도 값
tList.push(data['m2m:agr']['m2m:rsp'][2]['pc']['m2m:cin']['con']); // A3 구역 온도 값
tList.push(data['m2m:agr']['m2m:rsp'][3]['pc']['m2m:cin']['con']); // A4 구역 온도 값
console.log(tList);
tempCtx = document.getElementById('tempChart').getContext('2d');
tempConfig = {
type: 'bar', // 차트의 형태
data: { // 차트에 들어갈 데이터
labels: [
//x 축
'A1','A2','A3','A4'
],
datasets: [
{ //데이터
label: '', //차트 제목
fill: false, // line 형태일 때, 선 안쪽을 채우는지 안채우는지
data: tList,
backgroundColor: [
//색상
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)'
],
borderColor: [
//경계선 색상
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)'
],
borderWidth: 1 //경계선 굵기
}
]
},
options: {
legend: {
display: false
},
title: {
display : true, text: 'Temperature graph by zone'
},
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}
]
}
}
};
tempChart = new Chart(tempCtx, tempConfig);
startZoneCheckTempChart();
});
}
}).catch(err => console.error(err));
}
// 데이터 select해서 그래프에 그려지지 않은 데이터 있으면 추가
function checkZoneTempChart(){
selectGrpAsync('Zone', 'ztempgrp').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let newList = [];
newList.push(data['m2m:agr']['m2m:rsp'][0]['pc']['m2m:cin']['con']); // A1 구역 온도 값
newList.push(data['m2m:agr']['m2m:rsp'][1]['pc']['m2m:cin']['con']); // A2 구역 온도 값
newList.push(data['m2m:agr']['m2m:rsp'][2]['pc']['m2m:cin']['con']); // A3 구역 온도 값
newList.push(data['m2m:agr']['m2m:rsp'][3]['pc']['m2m:cin']['con']); // A4 구역 온도 값
if(JSON.stringify(tList)!=JSON.stringify(newList)){
console.log("temp data change detection");
//데이터셋 수 만큼 반복
var dataset = tempConfig.data.datasets;
var data = dataset[0].data;
for(var i=0 ; i < data.length ; i++){
data[i] = newList[i];
}
tempChart.update(); //차트 업데이트
let dangerList = [];
for(let i=0; i<4; i++){
if(data[i] > 48){
let str = 'A'+(i+1);
dangerList.push(str);
}
}
if(dangerList.length != 0){
$('#notiCard').show();
$('#td1').text(dangerList.toString()+' temperature is dangerous');
}
else{
$('#td1').text('');
if($('#td1').text() == '' && $('#td2').text()=='' && $('#td3').text()=='' && $('#td4').text()==''){
$('#notiCard').hide();
}
}
}
});
}
}).catch(err => console.error(err));
}
</script>
<!-- 구역별 습도 그래프 관련 -->
<script>
let hList = [];
let humiConfig;
let humiCtx;
let humiChart;
startZoneCheckHumiChart = function() {
playAlert = setInterval(function() {
checkZoneHumiChart();
}, 5000);
};
function drawZoneHumiChart(){
selectGrpAsync('Zone', 'zhumigrp').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
hList.push(data['m2m:agr']['m2m:rsp'][0]['pc']['m2m:cin']['con']); // A1 구역 온도 값
hList.push(data['m2m:agr']['m2m:rsp'][1]['pc']['m2m:cin']['con']); // A2 구역 온도 값
hList.push(data['m2m:agr']['m2m:rsp'][2]['pc']['m2m:cin']['con']); // A3 구역 온도 값
hList.push(data['m2m:agr']['m2m:rsp'][3]['pc']['m2m:cin']['con']); // A4 구역 온도 값
console.log(hList);
humiCtx = document.getElementById('humiChart').getContext('2d');
humiConfig = {
type: 'bar', // 차트의 형태
data: { // 차트에 들어갈 데이터
labels: [
//x 축
'A1','A2','A3','A4'
],
datasets: [
{ //데이터
label: '', //차트 제목
fill: false, // line 형태일 때, 선 안쪽을 채우는지 안채우는지
data: hList,
backgroundColor: [
//색상
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)'
],
borderColor: [
//경계선 색상
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)'
],
borderWidth: 1 //경계선 굵기
}
]
},
options: {
legend: {
display: false
},
title: {
display : true, text: 'Humidity graph by zone'
},
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}
]
}
}
};
humiChart = new Chart(humiCtx, humiConfig);
startZoneCheckHumiChart();
});
}
}).catch(err => console.error(err));
}
// 데이터 select해서 그래프에 그려지지 않은 데이터 있으면 추가
function checkZoneHumiChart(){
selectGrpAsync('Zone', 'zhumigrp').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let newList = [];
newList.push(data['m2m:agr']['m2m:rsp'][0]['pc']['m2m:cin']['con']); // A1 구역 온도 값
newList.push(data['m2m:agr']['m2m:rsp'][1]['pc']['m2m:cin']['con']); // A2 구역 온도 값
newList.push(data['m2m:agr']['m2m:rsp'][2]['pc']['m2m:cin']['con']); // A3 구역 온도 값
newList.push(data['m2m:agr']['m2m:rsp'][3]['pc']['m2m:cin']['con']); // A4 구역 온도 값
if(JSON.stringify(hList)!=JSON.stringify(newList)){
console.log("humi data change detection");
//데이터셋 수 만큼 반복
var dataset = humiConfig.data.datasets;
var data = dataset[0].data;
for(var i=0 ; i < data.length ; i++){
data[i] = newList[i];
}
humiChart.update(); //차트 업데이트
let dangerList = [];
for(let i=0; i<4; i++){
if(data[i] > 68){
let str = 'A'+(i+1);
dangerList.push(str);
}
}
if(dangerList.length != 0){
$('#notiCard').show();
$('#td2').text(dangerList.toString()+' humidity is dangerous');
}
else{
$('#td2').text('');
if($('#td1').text() == '' && $('#td2').text()=='' && $('#td3').text()=='' && $('#td4').text()==''){
$('#notiCard').hide();
}
}
}
});
}
}).catch(err => console.error(err));
}
</script>
<!-- 구역별 메탄가스 그래프 관련 -->
<script>
let mList = [];
let methConfig;
let methCtx;
let methChart;
startZoneCheckMethChart = function() {
playAlert = setInterval(function() {
checkZoneMethChart();
}, 5000);
};
function drawZoneMethChart(){
selectGrpAsync('Zone', 'zmethgrp').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
mList.push(data['m2m:agr']['m2m:rsp'][0]['pc']['m2m:cin']['con']);
mList.push(data['m2m:agr']['m2m:rsp'][1]['pc']['m2m:cin']['con']);
mList.push(data['m2m:agr']['m2m:rsp'][2]['pc']['m2m:cin']['con']);
mList.push(data['m2m:agr']['m2m:rsp'][3]['pc']['m2m:cin']['con']);
console.log(mList);
methCtx = document.getElementById('methChart').getContext('2d');
methConfig = {
type: 'bar', // 차트의 형태
data: { // 차트에 들어갈 데이터
labels: [
//x 축
'A1','A2','A3','A4'
],
datasets: [
{ //데이터
label: '', //차트 제목
fill: false, // line 형태일 때, 선 안쪽을 채우는지 안채우는지
data: mList,
backgroundColor: [
//색상
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)'
],
borderColor: [
//경계선 색상
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)'
],
borderWidth: 1 //경계선 굵기
}
]
},
options: {
legend: {
display: false
},
title: {
display : true, text: 'Methane gas graph by zone'
},
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}
]
}
}
};
methChart = new Chart(methCtx, methConfig);
startZoneCheckMethChart();
});
}
}).catch(err => console.error(err));
}
// 데이터 select해서 그래프에 그려지지 않은 데이터 있으면 추가
function checkZoneMethChart(){
selectGrpAsync('Zone', 'zmethgrp').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let newList = [];
newList.push(data['m2m:agr']['m2m:rsp'][0]['pc']['m2m:cin']['con']);
newList.push(data['m2m:agr']['m2m:rsp'][1]['pc']['m2m:cin']['con']);
newList.push(data['m2m:agr']['m2m:rsp'][2]['pc']['m2m:cin']['con']);
newList.push(data['m2m:agr']['m2m:rsp'][3]['pc']['m2m:cin']['con']);
if(JSON.stringify(mList)!=JSON.stringify(newList)){
console.log("meth data change detection");
//데이터셋 수 만큼 반복
var dataset = methConfig.data.datasets;
var data = dataset[0].data;
for(var i=0 ; i < data.length ; i++){
data[i] = newList[i];
}
methChart.update(); //차트 업데이트
let dangerList = [];
for(let i=0; i<4; i++){
if(data[i] > 48){
let str = 'A'+(i+1);
dangerList.push(str);
}
}
console.log("Methane Hazard Arrangement");
console.log(dangerList);
if(dangerList.length != 0){
$('#notiCard').show();
$('#td3').text(dangerList.toString()+' methane gas is dangerous.');
console.log("methane if!");
}
else{
$('#td3').text('');
console.log("methane else!");
console.log($('#td1').text() == '');
console.log($('#td2').text() == '');
console.log($('#td3').text() == '');
console.log($('#td4').text() == '');
if($('#td1').text() == '' && $('#td2').text()=='' && $('#td3').text()=='' && $('#td4').text()==''){
$('#notiCard').hide();
console.log("methane hide!");
}
}
}
});
}
}).catch(err => console.error(err));
}
</script>
<!-- 구역별 일산화탄소 그래프 관련 -->
<script>
let cList = [];
let cmonConfig;
let cmonCtx;
let cmonChart;
startZoneCheckCmonChart = function() {
playAlert = setInterval(function() {
checkZoneCmonChart();
}, 5000);
};
function drawZoneCmonChart(){
selectGrpAsync('Zone', 'zcmongrp').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
cList.push(data['m2m:agr']['m2m:rsp'][0]['pc']['m2m:cin']['con']);
cList.push(data['m2m:agr']['m2m:rsp'][1]['pc']['m2m:cin']['con']);
cList.push(data['m2m:agr']['m2m:rsp'][2]['pc']['m2m:cin']['con']);
cList.push(data['m2m:agr']['m2m:rsp'][3]['pc']['m2m:cin']['con']);
cmonCtx = document.getElementById('cmonChart').getContext('2d');
cmonConfig = {
type: 'bar', // 차트의 형태
data: { // 차트에 들어갈 데이터
labels: [
//x 축
'A1','A2','A3','A4'
],
datasets: [
{ //데이터
label: '', //차트 제목
fill: false, // line 형태일 때, 선 안쪽을 채우는지 안채우는지
data: cList,
backgroundColor: [
//색상
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)'
],
borderColor: [
//경계선 색상
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)'
],
borderWidth: 1 //경계선 굵기
}
]
},
options: {
legend: {
display: false
},
title: {
display : true, text: 'Cmonoxide graph by zone'
},
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}
]
}
}
};
cmonChart = new Chart(cmonCtx, cmonConfig);
startZoneCheckCmonChart();
});
}
}).catch(err => console.error(err));
}
// 데이터 select해서 그래프에 그려지지 않은 데이터 있으면 추가
function checkZoneCmonChart(){
selectGrpAsync('Zone', 'zcmongrp').then((res) => {
if (res.statusText == 'OK') {
res.json().then(data => {
let newList = [];
newList.push(data['m2m:agr']['m2m:rsp'][0]['pc']['m2m:cin']['con']);
newList.push(data['m2m:agr']['m2m:rsp'][1]['pc']['m2m:cin']['con']);
newList.push(data['m2m:agr']['m2m:rsp'][2]['pc']['m2m:cin']['con']);
newList.push(data['m2m:agr']['m2m:rsp'][3]['pc']['m2m:cin']['con']);
if(JSON.stringify(cList)!=JSON.stringify(newList)){
console.log("cmon data change detection");
//데이터셋 수 만큼 반복
var dataset = cmonConfig.data.datasets;
var data = dataset[0].data;
for(var i=0 ; i < data.length ; i++){
data[i] = newList[i];
}
cmonChart.update(); //차트 업데이트
let dangerList = [];
for(let i=0; i<4; i++){
if(data[i] > 48){
let str = 'A'+(i+1);
dangerList.push(str);
}
}
console.log("Cmonoxide Hazard Arrangement");
console.log(dangerList);
if(dangerList.length != 0){
$('#notiCard').show();
$('#td4').text(dangerList.toString()+' Cmonoxide is dangerous');
console.log("Cmonoxide if");
}
else{
$('#td4').textCmonoxide
console.log("일산화탄소 else");
if($('#td1').text() == '' && $('#td2').text()=='' && $('#td3').text()=='' && $('#td4').text()==''){
$('#notiCard').hide();
console.log("Cmonoxide hide");
}
}
}
});
}
}).catch(err => console.error(err));
}
</script>
</body>
<!-- Bootstrap core JavaScript -->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Plugin JavaScript -->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<script src="vendor/scrollreveal/scrollreveal.min.js"></script>
<script src="vendor/magnific-popup/jquery.magnific-popup.min.js"></script>
<!-- Custom scripts for this template -->
<script src="js/creative.min.js"></script>
</body>
</html>
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>가상 작업자</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<!-- jquery -->
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<!-- 모비우스 -->
<script src="./mobi-hero-mobius.js"></script>
<style>
p.state {
font-size: large;
font-weight: bold;
}
input{
display: inline-block;
}
</style>
<script>
$(document).ready(function() {
$('#btn1').click(function(){
if($('#btn1').text() == 'Go to work'){
$('#btn1').removeClass('btn-secondary');
$('#btn1').addClass('btn-primary');
$('#btn1').text('Off work');
createCin('worker1', 'location', "A1");
getWorker1();
startWorker1();
}
else if($('#btn1').text() == 'Off work'){
$('#btn1').removeClass('btn-primary');
$('#btn1').addClass('btn-secondary');
$('#btn1').text('Go to work');
// 임의로 처음 Go to work할 때만 Location 바뀌게 해놓음
createCin('worker1', 'location', "En");
stopWorker1();
}
else{ }
});
$('#btn2').click(function(){
if($('#btn2').text() == 'Go to work'){
$('#btn2').removeClass('btn-secondary');
$('#btn2').addClass('btn-primary');
$('#btn2').text('Off work');
createCin('worker2', 'location', "A2");
getWorker2();
startWorker2();
}
else if($('#btn2').text() == 'Off work'){
$('#btn2').removeClass('btn-primary');
$('#btn2').addClass('btn-secondary');
$('#btn2').text('Go to work');
// 임의로 처음 Go to work할 때만 Location 바뀌게 해놓음
createCin('worker2', 'location', "En");
stopWorker2();
}
else{ }
});
$('#btn3').click(function(){
if($('#btn3').text() == 'Go to work'){
$('#btn3').removeClass('btn-secondary');
$('#btn3').addClass('btn-primary');
$('#btn3').text('Off work');
createCin('worker3', 'location', "A1");
getWorker3();
startWorker3();
}
else if($('#btn3').text() == 'Off work'){
$('#btn3').removeClass('btn-primary');
$('#btn3').addClass('btn-secondary');
$('#btn3').text('Go to work');
// 임의로 처음 Go to work할 때만 Location 바뀌게 해놓음
createCin('worker3', 'location', "En");
stopWorker3();
}
else{ }
});
$('#btn4').click(function(){
if($('#btn4').text() == 'Go to work'){
$('#btn4').removeClass('btn-secondary');
$('#btn4').addClass('btn-primary');
$('#btn4').text('Off work');
createCin('worker4', 'location', "A2");
getWorker4();
startWorker4();
}
else if($('#btn4').text() == 'Off work'){
$('#btn4').removeClass('btn-primary');
$('#btn4').addClass('btn-secondary');
$('#btn4').text('Go to work');
// 임의로 처음 Go to work할 때만 Location 바뀌게 해놓음
createCin('worker4', 'location', "En");
stopWorker4();
}
else{ }
});
});
// 랜덤 값 생성 함수
function createRandomNumber(min, max){
let randNum = Math.floor(Math.random()*(max-min+1)) + min;
return randNum;
}
// 작업자 랜덤 데이터 생성
function createRandomWorkerDate() {
let arr = ['A1', 'A2', 'A3', 'A4']; // Off work할 때 location에 En 값 보내야 함
let idx = createRandomNumber(0, 3);
let location = arr[idx];
let temperature = createRandomNumber(15, 50);
let humidity = createRandomNumber(10, 70);
let methane = createRandomNumber(1, 50);
let cmonoxide = createRandomNumber(1, 50);
let heartrate = createRandomNumber(70, 90);
let danger = createRandomNumber(0, 10) < 10 ? 0 : 'fall';
let state;
if (temperature > 49 || humidity > 69 || methane > 49 || cmonoxide > 49 || heartrate < 71 || danger=='fall') {
state = 'danger';
}
else{
state = 0;
}
let list = {
"temperature" : temperature,
"humidity" : humidity,
"methane" : methane,
"cmonoxide" : cmonoxide,
"heartrate" : heartrate,
"location" : location,
"danger" : danger,
"state" : state
};
return list;
}
</script>
<!-- 작업자1 관련 -->
<script>
startWorker1 = function() {
playWorker1 = setInterval(function() {
getWorker1();
}, 3000);
};
stopWorker1 = function() {
enterWorker1();
clearInterval(playWorker1);
};
// 작업자1 Go to work : 랜덤값 생성하여 주기적으로 모비우스에 보냄
function getWorker1(){
let data = createRandomWorkerDate();
console.log(data);
$('#input1_loc').val("A1");
$('#input1_heart').val(data["heartrate"]);
$('#input1_danger').val(data["danger"]);
$('#input1_temp').val(data["temperature"]);
$('#input1_humi').val(data["humidity"]);
$('#input1_meth').val(data["methane"]);
$('#input1_cmon').val(data["cmonoxide"]);
if(data["state"] == 0){
$('#input1_state').text("SAFE");
$('#input1_state').css("color","black");
}
else{
$('#input1_state').text("DANGER");
$('#input1_state').css("color","red");
}
//createCin('worker1', 'location', data["location"]);
createCin('worker1', 'heartrate', data["heartrate"]);
createCin('worker1', 'temperature', data["temperature"]);
createCin('worker1', 'humidity', data["humidity"]);
createCin('worker1', 'methane', data["methane"]);
createCin('worker1', 'cmonoxide', data["cmonoxide"]);
createCin('worker1', 'danger', data["danger"]);
}
// 작업자1 Off work
function enterWorker1(){
$('#input1_loc').val("En");
$('#input1_heart').val('');
$('#input1_danger').val('');
$('#input1_temp').val('');
$('#input1_humi').val('');
$('#input1_meth').val('');
$('#input1_cmon').val('');
$('#input1_state').text("-");
$('#input1_state').css("color","black");
}
</script>
<!-- 작업자2 관련 -->
<script>
startWorker2 = function() {
playWorker2 = setInterval(function() {
getWorker2();
}, 3000);
};
stopWorker2 = function() {
enterWorker2();
clearInterval(playWorker2);
};
// 작업자2 Go to work : 랜덤값 생성하여 주기적으로 모비우스에 보냄
function getWorker2(){
let data = createRandomWorkerDate();
console.log(data);
$('#input2_loc').val("A2");
$('#input2_heart').val(data["heartrate"]);
$('#input2_danger').val(data["danger"]);
$('#input2_temp').val(data["temperature"]);
$('#input2_humi').val(data["humidity"]);
$('#input2_meth').val(data["methane"]);
$('#input2_cmon').val(data["cmonoxide"]);
if(data["state"] == 0){
$('#input2_state').text("SAFE");
$('#input2_state').css("color","black");
}
else{
$('#input2_state').text("DANGER");
$('#input2_state').css("color","red");
}
// createCin('worker2', 'location', data["location"]);
createCin('worker2', 'heartrate', data["heartrate"]);
createCin('worker2', 'temperature', data["temperature"]);
createCin('worker2', 'humidity', data["humidity"]);
createCin('worker2', 'methane', data["methane"]);
createCin('worker2', 'cmonoxide', data["cmonoxide"]);
createCin('worker2', 'danger', data["danger"]);
}
// 작업자2 Off work
function enterWorker2(){
$('#input2_loc').val("En");
$('#input2_heart').val('');
$('#input2_danger').val('');
$('#input2_temp').val('');
$('#input2_humi').val('');
$('#input2_meth').val('');
$('#input2_cmon').val('');
$('#input2_state').text("-");
$('#input2_state').css("color","black");
}
</script>
<!-- 작업자3 관련 -->
<script>
startWorker3 = function() {
playWorker3 = setInterval(function() {
getWorker3();
}, 3000);
};
stopWorker3 = function() {
enterWorker3();
clearInterval(playWorker3);
};
// 작업자3 Go to work : 랜덤값 생성하여 주기적으로 모비우스에 보냄
function getWorker3(){
let data = createRandomWorkerDate();
console.log(data);
$('#input3_loc').val("A4");
$('#input3_heart').val(data["heartrate"]);
$('#input3_danger').val(data["danger"]);
$('#input3_temp').val(data["temperature"]);
$('#input3_humi').val(data["humidity"]);
$('#input3_meth').val(data["methane"]);
$('#input3_cmon').val(data["cmonoxide"]);
if(data["state"] == 0){
$('#input3_state').text("SAFE");
$('#input3_state').css("color","black");
}
else{
$('#input3_state').text("DANGER");
$('#input3_state').css("color","red");
}
// createCin('worker3', 'location', data["location"]);
createCin('worker3', 'heartrate', data["heartrate"]);
createCin('worker3', 'temperature', data["temperature"]);
createCin('worker3', 'humidity', data["humidity"]);
createCin('worker3', 'methane', data["methane"]);
createCin('worker3', 'cmonoxide', data["cmonoxide"]);
createCin('worker3', 'danger', data["danger"]);
}
// 작업자3 Off work
function enterWorker3(){
$('#input3_loc').val("En");
$('#input3_heart').val('');
$('#input3_danger').val('');
$('#input3_temp').val('');
$('#input3_humi').val('');
$('#input3_meth').val('');
$('#input3_cmon').val('');
$('#input3_state').text("-");
$('#input3_state').css("color","black");
}
</script>
<!-- 작업자4 관련 -->
<script>
startWorker4 = function() {
playWorker4 = setInterval(function() {
getWorker4();
}, 3000);
};
stopWorker4 = function() {
enterWorker4();
clearInterval(playWorker4);
};
// 작업자4 Go to work : 랜덤값 생성하여 주기적으로 모비우스에 보냄
function getWorker4(){
let data = createRandomWorkerDate();
console.log(data);
$('#input4_loc').val("A2");
$('#input4_heart').val(data["heartrate"]);
$('#input4_danger').val(data["danger"]);
$('#input4_temp').val(data["temperature"]);
$('#input4_humi').val(data["humidity"]);
$('#input4_meth').val(data["methane"]);
$('#input4_cmon').val(data["cmonoxide"]);
if(data["state"] == 0){
$('#input4_state').text("SAFE");
$('#input4_state').css("color","black");
}
else{
$('#input4_state').text("DANGER");
$('#input4_state').css("color","red");
}
// createCin('worker4', 'location', data["location"]);
createCin('worker4', 'heartrate', data["heartrate"]);
createCin('worker4', 'temperature', data["temperature"]);
createCin('worker4', 'humidity', data["humidity"]);
createCin('worker4', 'methane', data["methane"]);
createCin('worker4', 'cmonoxide', data["cmonoxide"]);
createCin('worker4', 'danger', data["danger"]);
}
// 작업자4 Off work
function enterWorker4(){
$('#input4_loc').val("En");
$('#input4_heart').val('');
$('#input4_danger').val('');
$('#input4_temp').val('');
$('#input4_humi').val('');
$('#input4_meth').val('');
$('#input4_cmon').val('');
$('#input4_state').text("-");
$('#input4_state').css("color","black");
}
</script>
</head>
<body>
<br>
<div class="container">
<div class="row">
<div class="col-3">
<div class="card">
<div class="card-header">
worker1
<button id="btn1" class="btn btn-secondary btn-sm" style="float: right">Go to work</button>
</div>
<img src="img/worker2.png"alt="" />
<div class="card-body">
<table style="margin: 10px 0px; width: 100%; text-align: center;">
<tbody>
<tr>
<td><label for="input1_loc" class="form-label">Location</label></td>
<td><input type="text" class="form-control form-control-sm" id="input1_loc" placeholder="" style="width: 100px;" value="En"></td>
</tr>
<tr>
<td><label for="input1_heart" class="form-label">Heart Rate</label></td>
<td><input type="text" class="form-control form-control-sm" id="input1_heart" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input1_danger" class="form-label">DANGER</label></td>
<td><input type="text" class="form-control form-control-sm" id="input1_danger" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input1_temp" class="form-label">Temperature</label></td>
<td><input type="text" class="form-control form-control-sm" id="input1_temp" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input1_humi" class="form-label">Humidity</label></td>
<td><input type="text" class="form-control form-control-sm" id="input1_humi" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input1_meth" class="form-label">Methane</label></td>
<td><input type="text" class="form-control form-control-sm" id="input1_meth" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input1_cmon" class="form-label">Cmonoxide</label></td>
<td><input type="text" class="form-control form-control-sm" id="input1_cmon" placeholder="" style="width: 100px;"></td>
</tr>
</tbody>
</table>
<div style="text-align: center;"><p class="state" id="input1_state">-</p></div>
</div>
</div>
</div>
<div class="col-3">
<div class="card">
<div class="card-header">
worker2
<button id="btn2" class="btn btn-secondary btn-sm" style="float: right">Go to work</button>
</div>
<img src="img/worker2.png"alt="" />
<div class="card-body">
<table style="margin: 10px 0px; width: 100%; text-align: center;">
<tbody>
<tr>
<td><label for="input2_loc" class="form-label">Location</label></td>
<td><input type="text" class="form-control form-control-sm" id="input2_loc" placeholder="" style="width: 100px;" value="En"></td>
</tr>
<tr>
<td><label for="input2_heart" class="form-label">Heart Rate</label></td>
<td><input type="text" class="form-control form-control-sm" id="input2_heart" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input2_danger" class="form-label">DANGER</label></td>
<td><input type="text" class="form-control form-control-sm" id="input2_danger" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input2_temp" class="form-label">Temperature</label></td>
<td><input type="text" class="form-control form-control-sm" id="input2_temp" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input2_humi" class="form-label">Humidity</label></td>
<td><input type="text" class="form-control form-control-sm" id="input2_humi" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input2_meth" class="form-label">Methane</label></td>
<td><input type="text" class="form-control form-control-sm" id="input2_meth" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input2_cmon" class="form-label">Cmonoxide</label></td>
<td><input type="text" class="form-control form-control-sm" id="input2_cmon" placeholder="" style="width: 100px;"></td>
</tr>
</tbody>
</table>
<div style="text-align: center;"><p class="state" id="input2_state">-</p></div>
</div>
</div>
</div>
<div class="col-3">
<div class="card">
<div class="card-header">
worker3
<button id="btn3" class="btn btn-secondary btn-sm" style="float: right">Go to work</button>
</div>
<img src="img/worker2.png"alt="" />
<div class="card-body">
<table style="margin: 10px 0px; width: 100%; text-align: center;">
<tbody>
<tr>
<td><label for="input3_loc" class="form-label">Location</label></td>
<td><input type="text" class="form-control form-control-sm" id="input3_loc" placeholder="" style="width: 100px;" value="En"></td>
</tr>
<tr>
<td><label for="input3_heart" class="form-label">Heart Rate</label></td>
<td><input type="text" class="form-control form-control-sm" id="input3_heart" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input3_danger" class="form-label">DANGER</label></td>
<td><input type="text" class="form-control form-control-sm" id="input3_danger" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input3_temp" class="form-label">Temperature</label></td>
<td><input type="text" class="form-control form-control-sm" id="input3_temp" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input3_humi" class="form-label">Humidity</label></td>
<td><input type="text" class="form-control form-control-sm" id="input3_humi" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input3_meth" class="form-label">Methane</label></td>
<td><input type="text" class="form-control form-control-sm" id="input3_meth" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input3_cmon" class="form-label">Cmonoxide</label></td>
<td><input type="text" class="form-control form-control-sm" id="input3_cmon" placeholder="" style="width: 100px;"></td>
</tr>
</tbody>
</table>
<div style="text-align: center;"><p class="state" id="input3_state">-</p></div>
</div>
</div>
</div>
<div class="col-3">
<div class="card">
<div class="card-header">
worker4
<button id="btn4" class="btn btn-secondary btn-sm" style="float: right">Go to work</button>
</div>
<img src="img/worker2.png"alt="" />
<div class="card-body">
<table style="margin: 10px 0px; width: 100%; text-align: center;">
<tbody>
<tr>
<td><label for="input4_loc" class="form-label">Location</label></td>
<td><input type="text" class="form-control form-control-sm" id="input4_loc" placeholder="" style="width: 100px;" value="En"></td>
</tr>
<tr>
<td><label for="input4_heart" class="form-label">Heart Rate</label></td>
<td><input type="text" class="form-control form-control-sm" id="input4_heart" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input4_danger" class="form-label">DANGER</label></td>
<td><input type="text" class="form-control form-control-sm" id="input4_danger" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input4_temp" class="form-label">Temperature</label></td>
<td><input type="text" class="form-control form-control-sm" id="input4_temp" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input4_humi" class="form-label">Humidity</label></td>
<td><input type="text" class="form-control form-control-sm" id="input4_humi" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input4_meth" class="form-label">Methane</label></td>
<td><input type="text" class="form-control form-control-sm" id="input4_meth" placeholder="" style="width: 100px;"></td>
</tr>
<tr>
<td><label for="input4_cmon" class="form-label">Cmonoxide</label></td>
<td><input type="text" class="form-control form-control-sm" id="input4_cmon" placeholder="" style="width: 100px;"></td>
</tr>
</tbody>
</table>
<div style="text-align: center;"><p class="state" id="input4_state">-</p></div>
</div>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
</body>
</html>
#include <Arduino_LSM6DS3.h>
#include "DHT.h"
#define DHTPIN A6 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11 // DHT 11
DHT dht(DHTPIN, DHTTYPE);
// MQ-4 , MQ-7 +
int Mq_4 = A2; // MQ-4
int Mq_7 = A3; // MQ-7
//
#define mq4_d 30
#define mq7_d 30
#define t_d 45
#define h_d 60
//mq4 ppm
float RS_gas = 0;
float ratio = 0;
float sensorValue = 0;
float sensor_volt = 0;
float R0 = 7200.0;
//mq7 ppm
float RS_gas1 = 0;
float ratio1 = 0;
float sensorValue1 = 0;
float sensor_volt1 = 0;
float R01 = 7200.0;
unsigned long fallStartTime; //
unsigned long nowTime; //
boolean fallFirstState = true; //
boolean gyro = false;
int speaker = 2; //
//beacon
#include <ArduinoBLE.h>
void setup() {
Serial.begin(115200);
while (!Serial);
pinMode(Mq_4 ,INPUT); // A2
pinMode(Mq_7 ,INPUT); // A3
pinMode(7, INPUT); // 1
pinMode(8, INPUT); // 2
pinMode(2, OUTPUT); //
dht.begin();
if (!IMU.begin()) { //LSM6DS3
Serial.println("LSM6DS3 !");
while (1);
}
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
Serial.println("BLE Central scan");
BLE.scan();
}
String bleName = "";
char ble[100] = "None";
void Search_BLE() {
BLEDevice peripheral = BLE.available();
if (peripheral) {
//
if (peripheral.localName() == "En" || peripheral.localName() == "A1" || peripheral.localName() == "A2" || peripheral.localName() == "A3" || peripheral.localName() == "A4") {
Serial.println("Discovered a peripheral");
Serial.println("-----------------------");
// print address
Serial.print("localName: ");
bleName = peripheral.localName();
Serial.println(bleName);
if(bleName == "En")
bleName = "En";
int bleLen = bleName.length();
bleName.toCharArray(ble, bleLen+1);
Serial.print("ble");
Serial.println(ble);
}
}
}
float acc_x, acc_y, acc_z;
float acc_pit, acc_roll;
unsigned long rolltime = 0;
void danger_speaker(){
int i=0;
for( int i=0; i<=4; i++)
{
tone(2,900);
delay(500);
tone(2,800);
delay(500);
}
noTone(2);
}
void loop() {
//
nowTime = millis();
//beacon
Search_BLE();
float t = dht.readTemperature();
int h = dht.readHumidity();
int danger = 0;
//mq4 ppm
sensorValue = analogRead(A2);
sensor_volt = sensorValue/1024*5.0;
RS_gas = (5.0-sensor_volt)/sensor_volt;
ratio = RS_gas/R0; //Replace R0 with the value found using the sketch above
float x = 1538.46 * ratio;
int Mq4 = (float)pow(x,-1.709);
//mq7 ppm
sensorValue1 = analogRead(A3);
sensor_volt1 = sensorValue1/1024*5.0;
RS_gas1 = (5.0 - sensor_volt1)/sensor_volt1;
ratio1 = RS_gas1 / R01; //Replace R0 with the value found using the sketch above
float x1 = 1538.46 * ratio1;
int Mq7 = (float)pow(x1,-1.709);
//
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(acc_x, acc_y, acc_z);
//
acc_pit = RAD_TO_DEG * atan(acc_x / sqrt(acc_y*acc_y + acc_z*acc_z)); //
acc_roll = RAD_TO_DEG * atan(acc_y / sqrt(acc_x*acc_x + acc_z*acc_z));//180/PI = 57.27755
}
String matter_str = "";
char matter[500];
Search_BLE();
//
if(digitalRead(7)==0 && digitalRead(8)==0) {
Serial.println("");
//
Serial.print(" :");
Serial.println(acc_roll);
//
if(acc_roll < 10) {
if(fallFirstState) {
fallStartTime = millis();
fallFirstState = false;
}
if((nowTime - fallStartTime)/1000 > 5) {
fallFirstState = true;
gyro = true;
}
}
else {
fallFirstState = true;
}
if( Mq4 > mq4_d || Mq7 > mq7_d || t > t_d || h > h_d || gyro) {
Serial.println("");
//danger = -1;
if( Mq4 > mq4_d ) {
matter_str += "MQ4*";
}
if(Mq7 > mq7_d) {
matter_str += "MQ7*";
}
if(t > t_d) {
matter_str += "temp*";
}
if(h > h_d) {
matter_str += "humi*";
}
if(gyro) {
matter_str += "fall*";
gyro = false;
}
int len = matter_str.length();
matter_str.toCharArray(matter, len+1);
Serial.print("temperature: ");
Serial.println(t);
Serial.print("humidity: ");
Serial.println(h);
Serial.print("Mq4: ");
Serial.println(Mq4);
Serial.print("Mq7: ");
Serial.println(Mq7);
Serial.print("workSection: ");
Serial.println(ble);
Serial.print("danger: ");
Serial.println(matter);
Serial.println();
danger_speaker();
}
else {
danger = 0;
Serial.print("temperature: ");
Serial.println(t);
Serial.print("humidity: ");
Serial.println(h);
Serial.print("Mq4: ");
Serial.println(Mq4);
Serial.print("Mq7: ");
Serial.println(Mq7);
Serial.print("workSection: ");
Serial.println(ble);
Serial.print("danger: ");
Serial.println(danger);
Serial.println();
delay(1000);
}
}
//
else {
Serial.println("");
String WearOrNot = "NoWear";
char WON[50];
int Wlen = WearOrNot.length();
WearOrNot.toCharArray(WON, Wlen+1);
Serial.print("WearOrNot: ");
Serial.println(WON);
Serial.println();
}
}
Comments