Rewrite HomeKit pairing API
This commit is contained in:
+86
-84
@@ -59,7 +59,18 @@
|
||||
<body>
|
||||
<script src="main.js"></script>
|
||||
<script>
|
||||
async function getSources(url, tableID) {
|
||||
function drawTable(table, data) {
|
||||
const cols = ['id', 'name', 'info', 'url', 'location'];
|
||||
const th = (row) => cols.reduce((html, k) => k in row ? `${html}<th>${k}</th>` : html, '<tr>') + '</tr>';
|
||||
const td = (row) => cols.reduce((html, k) => k in row ? `${html}<td>${row[k]}</td>` : html, '<tr>') + '</tr>';
|
||||
|
||||
const thead = th(data.sources[0]);
|
||||
const tbody = data.sources.reduce((html, source) => `${html}${td(source)}`, '');
|
||||
|
||||
table.innerHTML = `<thead>${thead}</thead><tbody>${tbody}</tbody>`;
|
||||
}
|
||||
|
||||
async function getSources(tableID, url) {
|
||||
const table = document.getElementById(tableID);
|
||||
table.innerText = 'loading...';
|
||||
|
||||
@@ -69,16 +80,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const td = value => value ? `<td>${value}</td>` : '';
|
||||
const th = (name, value) => value ? `<th>${name}</th>` : '';
|
||||
|
||||
/** @type {{sources:Array<{id:string,name:string,url:string,location:string}>}} */
|
||||
const data = await r.json();
|
||||
const i0 = data.sources[0];
|
||||
const thead = `<tr>${th('ID', i0.id)}${th('Name', i0.name)}${th('URL', i0.url)}${th('Location', i0.location)}</tr>`;
|
||||
table.innerHTML = data.sources.reduce((html, item) => {
|
||||
return `${html}<tr>${td(item.id)}${td(item.name)}${td(item.url)}${td(item.location)}</tr>`;
|
||||
}, `<thead>${thead}</thead><tbody>`) + '</tbody>';
|
||||
drawTable(table, await r.json());
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -104,76 +106,79 @@
|
||||
url.searchParams.set('src', ev.target.elements['src'].value);
|
||||
|
||||
const r = await fetch(url, {method: 'PUT'});
|
||||
alert(r.ok ? 'OK' : 'ERROR');
|
||||
alert(r.ok ? 'OK' : 'ERROR: ' + await r.text());
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<button id="homekit">Apple HomeKit</button>
|
||||
<div class="module">
|
||||
<div style="margin-bottom: 10px">
|
||||
<label for="pin">PIN</label>
|
||||
<input id="pin" type="text">
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Address</th>
|
||||
<th>Model</th>
|
||||
<th>Commands</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="homekit-body">
|
||||
</tbody>
|
||||
</table>
|
||||
<form id="homekit-pair" style="margin-bottom: 10px">
|
||||
<input type="text" name="id" placeholder="stream id" size="20">
|
||||
<input type="text" name="url" placeholder="url" size="40">
|
||||
<input type="text" name="pin" placeholder="pin" size="10">
|
||||
<input type="submit" value="Pair">
|
||||
</form>
|
||||
<form id="homekit-unpair" style="margin-bottom: 10px">
|
||||
<input type="text" name="id" placeholder="stream id" size="20">
|
||||
<input type="submit" value="Unpair">
|
||||
</form>
|
||||
<table id="homekit-table"></table>
|
||||
</div>
|
||||
<script>
|
||||
async function reloadHomeKit() {
|
||||
await getSources('homekit-table', 'api/homekit');
|
||||
|
||||
const rows = document.querySelectorAll('#homekit-table tr');
|
||||
rows.forEach((row) => {
|
||||
let commands = '';
|
||||
if (row.children[2].innerText.indexOf('status=1') > 0) {
|
||||
commands += '<a href="#">pair</a>';
|
||||
} else if (row.children[3].innerText) {
|
||||
commands += '<a href="#">unpair</a>';
|
||||
}
|
||||
row.innerHTML += `<td>${commands}</td>`;
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById('homekit').addEventListener('click', async ev => {
|
||||
ev.target.nextElementSibling.style.display = 'block';
|
||||
const r = await fetch('api/homekit', {cache: 'no-cache'});
|
||||
|
||||
/** @type {Array<{id:string,name:string,addr:string,model:string,paired:boolean}>} */
|
||||
const data = await r.json();
|
||||
|
||||
const tbody = document.getElementById('homekit-body');
|
||||
tbody.innerHTML =
|
||||
data.reduce((res, item) => {
|
||||
let commands = '';
|
||||
if (item.id === '') {
|
||||
commands = `<a href="#" onclick="unpair('${item.name}')">unpair</a>`;
|
||||
} else if (item.paired === false) {
|
||||
commands = `<a href="#" onclick="pair('${item.id}','${item.name}')">pair</a>`;
|
||||
}
|
||||
return res + `<tr>
|
||||
<td>${item.name}</td>
|
||||
<td>${item.addr}</td>
|
||||
<td>${item.model}</td>
|
||||
<td>${commands}</td>
|
||||
</tr>`;
|
||||
}, '');
|
||||
await reloadHomeKit();
|
||||
});
|
||||
|
||||
function pair(id, name) {
|
||||
const pin = document.querySelector('#pin').value;
|
||||
fetch(`api/homekit?id=${id}&name=${name}&pin=${pin}`, {method: 'POST'})
|
||||
.then(r => r.text())
|
||||
.then(data => {
|
||||
if (data.length > 0) alert(data);
|
||||
else window.location.reload();
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
document.getElementById('homekit-table').addEventListener('click', ev => {
|
||||
if (ev.target.innerText === 'pair') {
|
||||
const form = document.querySelector('#homekit-pair');
|
||||
const row = ev.target.closest('tr');
|
||||
form.children[0].value = row.children[0].innerText;
|
||||
form.children[1].value = row.children[2].innerText;
|
||||
} else if (ev.target.innerText === 'unpair') {
|
||||
const form = document.querySelector('#homekit-unpair');
|
||||
const row = ev.target.closest('tr');
|
||||
form.children[0].value = row.children[3].innerText;
|
||||
}
|
||||
});
|
||||
|
||||
function unpair(src) {
|
||||
fetch(`api/homekit?src=${src}`, {method: 'DELETE'})
|
||||
.then(r => r.text())
|
||||
.then(data => {
|
||||
if (data.length > 0) alert(data);
|
||||
else window.location.reload();
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
document.getElementById('homekit-pair').addEventListener('submit', async ev => {
|
||||
ev.preventDefault();
|
||||
|
||||
const body = new FormData(ev.target);
|
||||
body.set('url', body.get('url') + '&pin=' + body.get('pin'));
|
||||
body.delete('pin');
|
||||
|
||||
const r = await fetch('api/homekit', {method: 'POST', body: body});
|
||||
alert(r.ok ? 'OK' : 'ERROR: ' + await r.text());
|
||||
|
||||
await reloadHomeKit();
|
||||
});
|
||||
|
||||
document.getElementById('homekit-unpair').addEventListener('submit', async ev => {
|
||||
ev.preventDefault();
|
||||
const r = await fetch('api/homekit', {method: 'DELETE', body: new FormData(ev.target)});
|
||||
alert(r.ok ? 'OK' : 'ERROR: ' + await r.text());
|
||||
|
||||
await reloadHomeKit();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -184,33 +189,31 @@
|
||||
<script>
|
||||
document.getElementById('dvrip').addEventListener('click', async ev => {
|
||||
ev.target.nextElementSibling.style.display = 'block';
|
||||
await getSources('api/dvrip', 'dvrip-table');
|
||||
await getSources('dvrip-table', 'api/dvrip');
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<button id="devices">FFmpeg Devices (USB)</button>
|
||||
<div class="module">
|
||||
<table id="devices-table">
|
||||
</table>
|
||||
<table id="devices-table"></table>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById('devices').addEventListener('click', async ev => {
|
||||
ev.target.nextElementSibling.style.display = 'block';
|
||||
await getSources('api/ffmpeg/devices', 'devices-table');
|
||||
await getSources('devices-table', 'api/ffmpeg/devices');
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<button id="hardware">FFmpeg Hardware</button>
|
||||
<div class="module">
|
||||
<table id="hardware-table">
|
||||
</table>
|
||||
<table id="hardware-table"></table>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById('hardware').addEventListener('click', async ev => {
|
||||
ev.target.nextElementSibling.style.display = 'block';
|
||||
await getSources('api/ffmpeg/hardware', 'hardware-table');
|
||||
await getSources('hardware-table', 'api/ffmpeg/hardware');
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -224,8 +227,7 @@
|
||||
<input type="text" name="project_id" placeholder="project_id">
|
||||
<input type="submit" value="Login">
|
||||
</form>
|
||||
<table id="nest-table">
|
||||
</table>
|
||||
<table id="nest-table"></table>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById('nest').addEventListener('click', async ev => {
|
||||
@@ -239,7 +241,7 @@
|
||||
const url = new URL('api/nest?' + query.toString(), location.href);
|
||||
|
||||
const r = await fetch(url, {cache: 'no-cache'});
|
||||
await getSources(r, 'nest-table');
|
||||
await getSources('nest-table', r);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -251,7 +253,7 @@
|
||||
<script>
|
||||
document.getElementById('hass').addEventListener('click', async ev => {
|
||||
ev.target.nextElementSibling.style.display = 'block';
|
||||
await getSources('api/hass', 'hass-table');
|
||||
await getSources('hass-table', 'api/hass');
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -267,7 +269,7 @@
|
||||
<script>
|
||||
document.getElementById('onvif').addEventListener('click', async ev => {
|
||||
ev.target.nextElementSibling.style.display = 'block';
|
||||
await getSources('api/onvif', 'onvif-table');
|
||||
await getSources('onvif-table', 'api/onvif');
|
||||
});
|
||||
|
||||
document.getElementById('onvif-form').addEventListener('submit', async ev => {
|
||||
@@ -276,7 +278,7 @@
|
||||
const url = new URL('api/onvif', location.href);
|
||||
url.searchParams.set('src', ev.target.elements['src'].value);
|
||||
|
||||
await getSources(url.toString(), 'onvif-table');
|
||||
await getSources('onvif-table', url.toString());
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -294,13 +296,13 @@
|
||||
<script>
|
||||
document.getElementById('roborock').addEventListener('click', async ev => {
|
||||
ev.target.nextElementSibling.style.display = 'block';
|
||||
await getSources('api/roborock', 'roborock-table');
|
||||
await getSources('roborock-table', 'api/roborock');
|
||||
});
|
||||
|
||||
document.getElementById('roborock-form').addEventListener('submit', async ev => {
|
||||
ev.preventDefault();
|
||||
const r = await fetch('api/roborock', {method: 'POST', body: new FormData(ev.target)});
|
||||
await getSources(r, 'roborock-table');
|
||||
await getSources('roborock-table', r);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -312,7 +314,7 @@
|
||||
<script>
|
||||
document.getElementById('webtorrent').addEventListener('click', async ev => {
|
||||
ev.target.nextElementSibling.style.display = 'block';
|
||||
await getSources('api/webtorrent', 'webtorrent-table');
|
||||
await getSources('webtorrent-table', 'api/webtorrent');
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user