Motions / index.html
OzoneAsai's picture
Update index.html
08eeeee verified
<!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>
// サーバーURL
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();
}
}
// サーバーURLを設定
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 = "ステータス: 記録停止";
}
// CSVにエクスポート
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); // Firefoxでは必要
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>