|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>HTTP with Client-Side Sensor Data and Flags</title> |
|
<style> |
|
body { |
|
font-family: Arial, sans-serif; |
|
} |
|
#container { |
|
margin: 50px; |
|
} |
|
#output, #client-refresh, #client-sensor, #controls, #flags, #export, #send-data, #send-flags { |
|
margin-top: 10px; |
|
padding: 10px; |
|
border: 1px solid #ccc; |
|
background-color: #f9f9f9; |
|
width: 320px; |
|
} |
|
#status { |
|
margin-top: 10px; |
|
font-weight: bold; |
|
} |
|
#error { |
|
margin-top: 10px; |
|
color: red; |
|
} |
|
button { |
|
margin-right: 5px; |
|
margin-bottom: 5px; |
|
} |
|
.flag-button.active { |
|
background-color: #4CAF50; |
|
color: white; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div id="container"> |
|
<h1>HTTP & Client-Side Sensor Data with Flags</h1> |
|
<p>データを送信するサーバーのURLを指定してください(例: https://example.com/api/):</p> |
|
<input type="text" id="server-url" placeholder="https://example.com/api/"> |
|
<div id="send-flags"> |
|
<button onclick="setServerUrl()">設定</button> |
|
</div> |
|
|
|
<div id="controls"> |
|
<button onclick="startRecording()">記録開始</button> |
|
<button onclick="stopRecording()">記録停止</button> |
|
</div> |
|
|
|
<div id="flags"> |
|
<h3>フラグ設定</h3> |
|
<button id="flag-start" class="flag-button" onclick="toggleFlag('start')">Start</button> |
|
<button id="flag-stop" class="flag-button" onclick="toggleFlag('stop')">Stop</button> |
|
<button id="flag-pause" class="flag-button" onclick="toggleFlag('pause')">Pause</button> |
|
<button id="flag-walk" class="flag-button" onclick="toggleFlag('walk')">Walk</button> |
|
<button id="flag-inBag" class="flag-button" onclick="toggleFlag('inBag')">In Bag</button> |
|
<button id="flag-inPocket" class="flag-button" onclick="toggleFlag('inPocket')">In Pocket</button> |
|
<button id="flag-inHand" class="flag-button" onclick="toggleFlag('inHand')">In Hand</button> |
|
<div id="current-flags"> |
|
<strong>現在のフラグ:</strong> なし |
|
</div> |
|
<button onclick="sendFlagsToServer()">フラグを送信</button> |
|
</div> |
|
|
|
<div id="export"> |
|
<button onclick="exportToCSV()">CSVとしてエクスポート</button> |
|
</div> |
|
<div id="send-data"> |
|
<button onclick="sendDataToServer()">データを送信</button> |
|
</div> |
|
|
|
<div id="status">Status: Not connected</div> |
|
<div id="output">最新サーバーデータがここに表示されます</div> |
|
<div id="client-sensor">クライアントサイドデータ: 加速度と回転率がここに表示されます</div> |
|
<div id="client-refresh">クライアント リフレッシュレート: 計測中...</div> |
|
<div id="error">エラー: なし</div> |
|
</div> |
|
|
|
<script> |
|
|
|
let serverUrl = ''; |
|
|
|
|
|
let isRecording = false; |
|
let sensorData = []; |
|
|
|
|
|
const flags = { |
|
start: false, |
|
stop: false, |
|
pause: false, |
|
walk: false, |
|
inBag: false, |
|
inPocket: false, |
|
inHand: false |
|
}; |
|
|
|
|
|
function updateFlagButtons() { |
|
for (let key in flags) { |
|
const button = document.getElementById(`flag-${key}`); |
|
if (flags[key]) { |
|
button.classList.add('active'); |
|
} else { |
|
button.classList.remove('active'); |
|
} |
|
} |
|
|
|
|
|
const activeFlags = Object.keys(flags).filter(key => flags[key]); |
|
const currentFlagsDiv = document.getElementById('current-flags'); |
|
currentFlagsDiv.innerHTML = `<strong>現在のフラグ:</strong> ${activeFlags.length > 0 ? activeFlags.join(', ') : 'なし'}`; |
|
} |
|
|
|
|
|
function toggleFlag(flag) { |
|
if (flags.hasOwnProperty(flag)) { |
|
flags[flag] = !flags[flag]; |
|
updateFlagButtons(); |
|
} |
|
} |
|
|
|
|
|
function setServerUrl() { |
|
const inputUrl = document.getElementById('server-url').value.trim(); |
|
if (inputUrl) { |
|
serverUrl = inputUrl.endsWith('/') ? inputUrl : inputUrl + '/'; |
|
document.getElementById('status').innerHTML = `Status: Server URL set to ${serverUrl}`; |
|
document.getElementById('error').innerHTML = "エラー: なし"; |
|
} else { |
|
alert("有効なサーバーURLを入力してください。"); |
|
} |
|
} |
|
|
|
|
|
function requestSensorPermissions() { |
|
try { |
|
if (typeof DeviceMotionEvent.requestPermission === 'function') { |
|
DeviceMotionEvent.requestPermission() |
|
.then(permissionState => { |
|
if (permissionState === 'granted') { |
|
document.getElementById('status').innerHTML = "センサーアクセスが許可されました"; |
|
startMotionDetection(); |
|
} else { |
|
document.getElementById('status').innerHTML = "センサーアクセスが拒否されました"; |
|
} |
|
}) |
|
.catch(error => { |
|
handleError(error); |
|
}); |
|
} else { |
|
|
|
startMotionDetection(); |
|
} |
|
} catch (error) { |
|
handleError(error); |
|
} |
|
} |
|
|
|
|
|
function startMotionDetection() { |
|
try { |
|
window.addEventListener('devicemotion', function(event) { |
|
let acceleration = event.accelerationIncludingGravity; |
|
let rotationRate = event.rotationRate; |
|
let timestamp = event.timeStamp; |
|
|
|
let sensorInfo = { |
|
timestamp: timestamp, |
|
acceleration: { |
|
x: acceleration.x, |
|
y: acceleration.y, |
|
z: acceleration.z |
|
}, |
|
rotationRate: { |
|
alpha: rotationRate.alpha, |
|
beta: rotationRate.beta, |
|
gamma: rotationRate.gamma |
|
}, |
|
flags: { ...flags } |
|
}; |
|
|
|
document.getElementById('client-sensor').innerHTML = |
|
`加速度: <br> X: ${acceleration.x} <br> Y: ${acceleration.y} <br> Z: ${acceleration.z} <br>` + |
|
`回転率: <br> alpha: ${rotationRate.alpha} <br> beta: ${rotationRate.beta} <br> gamma: ${rotationRate.gamma}`; |
|
|
|
if (isRecording) { |
|
sensorData.push(sensorInfo); |
|
} |
|
|
|
|
|
sendFlagsToServer(); |
|
}); |
|
} catch (error) { |
|
handleError(error); |
|
} |
|
} |
|
|
|
|
|
function startRecording() { |
|
sensorData = []; |
|
isRecording = true; |
|
document.getElementById('status').innerHTML = "ステータス: 記録中..."; |
|
} |
|
|
|
|
|
function stopRecording() { |
|
isRecording = false; |
|
document.getElementById('status').innerHTML = "ステータス: 記録停止"; |
|
} |
|
|
|
|
|
function exportToCSV() { |
|
if (sensorData.length === 0) { |
|
alert("記録されたデータがありません。"); |
|
return; |
|
} |
|
|
|
let csvContent = "data:text/csv;charset=utf-8,"; |
|
csvContent += "timestamp,acceleration_x,acceleration_y,acceleration_z,rotation_alpha,rotation_beta,rotation_gamma,flags\n"; |
|
|
|
sensorData.forEach(function(row) { |
|
let flagsString = Object.keys(row.flags).filter(key => row.flags[key]).join(';') || 'none'; |
|
let dataString = `${row.timestamp},${row.acceleration.x},${row.acceleration.y},${row.acceleration.z},${row.rotationRate.alpha},${row.rotationRate.beta},${row.rotationRate.gamma},${flagsString}`; |
|
csvContent += dataString + "\n"; |
|
}); |
|
|
|
let encodedUri = encodeURI(csvContent); |
|
let link = document.createElement("a"); |
|
link.setAttribute("href", encodedUri); |
|
let currentDate = new Date(); |
|
let filename = `sensor_data_${currentDate.getFullYear()}-${String(currentDate.getMonth()+1).padStart(2, '0')}-${String(currentDate.getDate()).padStart(2, '0')}_${String(currentDate.getHours()).padStart(2, '0')}-${String(currentDate.getMinutes()).padStart(2, '0')}-${String(currentDate.getSeconds()).padStart(2, '0')}.csv`; |
|
link.setAttribute("download", filename); |
|
document.body.appendChild(link); |
|
link.click(); |
|
document.body.removeChild(link); |
|
} |
|
|
|
|
|
function sendDataToServer() { |
|
if (sensorData.length === 0) { |
|
alert("送信するデータがありません。"); |
|
return; |
|
} |
|
|
|
if (!serverUrl) { |
|
alert("サーバーURLを設定してください。"); |
|
return; |
|
} |
|
|
|
fetch(`${serverUrl}sensor-data`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json' |
|
}, |
|
body: JSON.stringify(sensorData) |
|
}) |
|
.then(response => { |
|
if (response.ok) { |
|
alert("データが正常に送信されました。"); |
|
document.getElementById('output').innerHTML = "データがサーバーに送信されました。"; |
|
} else { |
|
alert("データの送信に失敗しました。ステータスコード: " + response.status); |
|
} |
|
}) |
|
.catch(error => { |
|
handleError(error); |
|
}); |
|
} |
|
|
|
|
|
function sendFlagsToServer() { |
|
if (!serverUrl) { |
|
console.warn("サーバーURLが設定されていません。フラグを送信できません。"); |
|
return; |
|
} |
|
|
|
|
|
fetch(`${serverUrl}flags`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json' |
|
}, |
|
body: JSON.stringify({ flags: { ...flags } }) |
|
}) |
|
.then(response => { |
|
if (response.ok) { |
|
console.log("フラグが正常に送信されました。"); |
|
} else { |
|
console.error("フラグの送信に失敗しました。ステータスコード: " + response.status); |
|
} |
|
}) |
|
.catch(error => { |
|
handleError(error); |
|
}); |
|
} |
|
|
|
|
|
function handleError(error) { |
|
console.error(error); |
|
let errorMessage = error.message || error; |
|
document.getElementById('error').innerHTML = "エラー: " + errorMessage; |
|
} |
|
|
|
|
|
window.onload = function() { |
|
updateFlagButtons(); |
|
}; |
|
</script> |
|
</body> |
|
</html> |
|
|