@homebridge-plugins/homebridge-air
Version:
The AirNow plugin allows you to monitor the current AirQuality for your Zip Code from HomeKit and Siri.
338 lines (323 loc) • 15.7 kB
HTML
<p class="text-center">
<img src="https://raw.githubusercontent.com/homebridge-plugins/homebridge-air/latest/branding/Homebridge_x_Air.svg"
alt="homebridge-air logo" style="width: 40%" />
</p>
<div id="pageIntro" style="display: none">
<p class="lead text-center">Thank you for installing <strong>homebridge-air</strong></p>
<p class="lead text-center">Before continuing:</p>
<ol>
<li class="mb-3">Login / create an account at <a href="https://docs.airnowapi.org/faq" target="_blank"
rel="noreferrer noopener">https://docs.airnowapi.org/faq</a>.</li>
<li class="mb-3">Click <strong>Web Services</strong>.</li>
<li>Copy Your API Key in the top right.</li>
</ol>
<div class="text-center">
<button type="button" class="btn btn-primary" id="introLink">Continue →</button>
</div>
</div>
<div id="menuWrapper" class="btn-group w-100 mb-0" role="group" aria-label="UI Menu" style="display: none">
<button type="button" class="btn btn-primary" id="menuLocation">Location</button>
<button type="button" class="btn btn-primary" id="menuSettings">Settings</button>
<button type="button" class="btn btn-primary" id="menuDevices">Devices</button>
<button type="button" class="btn btn-primary mr-0" id="menuHome">Support</button>
</div>
<div id="disabledBanner" class="alert alert-secondary mb-0 mt-3" role="alert" style="display: none">
Plugin is currently disabled
<button id="disabledEnable" type="button" class="btn btn-link p-0 m-0 float-right">Enable</button>
</div>
<div id="pageLocation" style="display: none;">
<button type="button" class="btn btn-primary mb-3" id="getLocation">Use Current Location</button>
<div class="mb-2">
<label for="latitudeField">Latitude:</label>
<input type="text" id="latitudeField" name="latitude">
<button type="button" class="btn btn-outline-secondary btn-sm" id="copyLatitude">Copy</button>
</div>
<div>
<label for="longitudeField">Longitude:</label>
<input type="text" id="longitudeField" name="longitude">
<button type="button" class="btn btn-outline-secondary btn-sm" id="copyLongitude">Copy</button>
</div>
</div>
<div id="pageDevices" class="mt-4" style="display: none">
<div id="deviceInfo">
<form>
<div class="form-group">
<select class="form-control" id="deviceSelect"></select>
</div>
</form>
<table class="table w-100" id="deviceTable" style="display: none">
<thead>
<tr class="table-active">
<th scope="col" style="width: 40%">Device Name</th>
<th scope="col" style="width: 60%" id="displayName"></th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Serial Number</th>
<td id="serialNumber"></td>
</tr>
<tr>
<th scope="row">Model</th>
<td id="model"></td>
</tr>
<tr>
<th scope="row">Firmware Version</th>
<td id="firmwareRevision"></td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="pageSupport" class="mt-4" style="display: none">
<p class="text-center lead">Thank you for using <strong>homebridge-air</strong></p>
<p class="text-center">The links below will take you to our GitHub wiki</p>
<h5>Setup</h5>
<ul>
<li>
<a href="https://github.com/homebridge-plugins/homebridge-air/wiki" target="_blank">Wiki Home</a>
</li>
<li>
<a href="https://github.com/homebridge-plugins/homebridge-air/wiki/Configuration" target="_blank">Configuration</a>
</li>
<li>
<a href="https://github.com/homebridge-plugins/homebridge-air/wiki/Beta-Version" target="_blank">Beta Version</a>
</li>
<li>
<a href="https://github.com/homebridge-plugins/homebridge-air/wiki/Node-Version" target="_blank">Node Version</a>
</li>
<li>
<a href="https://github.com/homebridge-plugins/homebridge-air/wiki/Uninstallation" target="_blank">Uninstallation</a>
</li>
</ul>
<h5>Features</h5>
<ul>
<li>
<a href="https://github.com/homebridge-plugins/homebridge-air/wiki/Supported-Devices" target="_blank">Supported
Devices</a>
</li>
<li>
<a href="https://github.com/homebridge-plugins/homebridge-air/wiki/Fan-Modes" target="_blank">Fan Modes</a>
</li>
</ul>
<h5>Help/About</h5>
<ul>
<li>
<a href="https://github.com/homebridge-plugins/homebridge-air/issues/new/choose" target="_blank">Support Request</a>
</li>
<li>
<a href="https://github.com/homebridge-plugins/homebridge-air/blob/latest/CHANGELOG.md" target="_blank">Changelog</a>
</li>
<li>
<a href="https://github.com/sponsors/donavanbecker" target="_blank">About Me</a>
</li>
</ul>
<h5>Disclaimer</h5>
<ul>
<li>I am in no way affiliated with Airnow and this plugin is a personal project that I maintain in my free time.
</li>
<li>Use this plugin entirely at your own risk - please see licence for more information.</li>
</ul>
</div>
<script>
(async () => {
try {
const currentConfig = await homebridge.getPluginConfig();
const showIntro = () => {
const introLink = document.getElementById('introLink');
introLink.addEventListener('click', () => {
homebridge.showSpinner();
document.getElementById('pageIntro').style.display = 'none';
document.getElementById('menuWrapper').style.display = 'inline-flex';
showLocation();
homebridge.hideSpinner();
});
document.getElementById('menuWrapper').style.display = 'none';
document.getElementById('pageIntro').style.display = 'block';
};
const showDevices = async () => {
homebridge.showSpinner();
homebridge.hideSchemaForm();
document.getElementById('menuHome').classList.remove('btn-elegant');
document.getElementById('menuHome').classList.add('btn-primary');
document.getElementById('menuDevices').classList.add('btn-elegant');
document.getElementById('menuDevices').classList.remove('btn-primary');
document.getElementById('menuLocation').classList.remove('btn-elegant');
document.getElementById('menuLocation').classList.add('btn-primary');
document.getElementById('menuSettings').classList.remove('btn-elegant');
document.getElementById('menuSettings').classList.add('btn-primary');
document.getElementById('pageLocation').style.display = 'none';
document.getElementById('pageSupport').style.display = 'none';
document.getElementById('pageDevices').style.display = 'block';
const cachedAccessories =
typeof homebridge.getCachedAccessories === 'function'
? await homebridge.getCachedAccessories()
: await homebridge.request('/getCachedAccessories');
if (cachedAccessories.length > 0) {
cachedAccessories.sort((a, b) => {
return a.displayName.toLowerCase() > b.displayName.toLowerCase() ? 1 : b.displayName.toLowerCase() > a.displayName.toLowerCase() ? -1 : 0;
});
}
const deviceSelect = document.getElementById('deviceSelect');
deviceSelect.innerHTML = '';
cachedAccessories.forEach((a) => {
const option = document.createElement('option');
option.text = a.displayName;
option.value = a.UUID;
deviceSelect.add(option);
});
const showDeviceInfo = async (UUID) => {
homebridge.showSpinner();
const thisAcc = cachedAccessories.find((x) => x.UUID === UUID);
const context = thisAcc.context;
document.getElementById('displayName').innerHTML = thisAcc.displayName;
document.getElementById('serialNumber').innerHTML = context.serialNumber;
document.getElementById('model').innerHTML = context.model;
document.getElementById('firmwareRevision').innerHTML = context.firmwareRevision || 'N/A';
document.getElementById('deviceTable').style.display = 'inline-table';
homebridge.hideSpinner();
};
deviceSelect.addEventListener('change', (event) => showDeviceInfo(event.target.value));
if (cachedAccessories.length > 0) {
showDeviceInfo(cachedAccessories[0].UUID);
} else {
const option = document.createElement('option');
option.text = 'No Devices';
deviceSelect.add(option);
deviceSelect.disabled = true;
}
homebridge.hideSpinner();
};
const showSupport = () => {
homebridge.showSpinner();
homebridge.hideSchemaForm();
document.getElementById('menuHome').classList.add('btn-elegant');
document.getElementById('menuHome').classList.remove('btn-primary');
document.getElementById('menuDevices').classList.remove('btn-elegant');
document.getElementById('menuDevices').classList.add('btn-primary');
document.getElementById('menuLocation').classList.remove('btn-elegant');
document.getElementById('menuLocation').classList.add('btn-primary');
document.getElementById('menuSettings').classList.remove('btn-elegant');
document.getElementById('menuSettings').classList.add('btn-primary');
document.getElementById('pageLocation').style.display = 'none';
document.getElementById('pageSupport').style.display = 'block';
document.getElementById('pageDevices').style.display = 'none';
homebridge.hideSpinner();
};
const showLocation = () => {
document.getElementById('getLocation').addEventListener('click', () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
// Assign the latitude and longitude to the input fields
document.getElementById('latitudeField').value = latitude;
document.getElementById('longitudeField').value = longitude;
homebridge.toast.success('Location fetched successfully.', 'Success');
}, (error) => {
let errorMessage = 'Error getting location: ';
switch (error.code) {
case error.PERMISSION_DENIED:
errorMessage += 'User denied the request for Geolocation.';
break;
case error.POSITION_UNAVAILABLE:
errorMessage += 'Location information is unavailable.';
break;
case error.TIMEOUT:
errorMessage += 'The request to get user location timed out.';
break;
case error.UNKNOWN_ERROR:
errorMessage += 'An unknown error occurred.';
break;
}
console.error(errorMessage, error);
homebridge.toast.error(errorMessage, 'Error');
});
} else {
homebridge.toast.error('Geolocation is not supported by this browser.', 'Error');
}
});
document.getElementById('copyLatitude').addEventListener('click', () => {
const latitude = document.getElementById('latitudeField').value;
navigator.clipboard.writeText(latitude).then(() => {
homebridge.toast.success('Latitude copied to clipboard.', 'Success');
}).catch((error) => {
console.error('Error copying latitude:', error);
homebridge.toast.error('Error copying latitude: ' + error.message, 'Error');
});
});
document.getElementById('copyLongitude').addEventListener('click', () => {
const longitude = document.getElementById('longitudeField').value;
navigator.clipboard.writeText(longitude).then(() => {
homebridge.toast.success('Longitude copied to clipboard.', 'Success');
}).catch((error) => {
console.error('Error copying longitude:', error);
homebridge.toast.error('Error copying longitude: ' + error.message, 'Error');
});
});
homebridge.showSpinner();
homebridge.hideSchemaForm();
document.getElementById('menuHome').classList.remove('btn-elegant');
document.getElementById('menuHome').classList.add('btn-primary');
document.getElementById('menuDevices').classList.remove('btn-elegant');
document.getElementById('menuDevices').classList.add('btn-primary');
document.getElementById('menuLocation').classList.add('btn-elegant');
document.getElementById('menuLocation').classList.remove('btn-primary');
document.getElementById('menuSettings').classList.remove('btn-elegant');
document.getElementById('menuSettings').classList.add('btn-primary');
document.getElementById('pageLocation').style.display = 'block';
document.getElementById('pageSupport').style.display = 'none';
document.getElementById('pageDevices').style.display = 'none';
homebridge.hideSpinner();
};
document.getElementById('menuLocation').addEventListener('click', showLocation);
const showSettings = () => {
homebridge.showSpinner();
document.getElementById('menuHome').classList.remove('btn-elegant');
document.getElementById('menuHome').classList.add('btn-primary');
document.getElementById('menuDevices').classList.remove('btn-elegant');
document.getElementById('menuDevices').classList.add('btn-primary');
document.getElementById('menuLocation').classList.remove('btn-elegant');
document.getElementById('menuLocation').classList.add('btn-primary');
document.getElementById('menuSettings').classList.add('btn-elegant');
document.getElementById('menuSettings').classList.remove('btn-primary');
document.getElementById('pageLocation').style.display = 'none';
document.getElementById('pageSupport').style.display = 'none';
document.getElementById('pageDevices').style.display = 'none';
homebridge.showSchemaForm();
homebridge.hideSpinner();
};
const showDisabledBanner = () => {
document.getElementById('disabledBanner').style.display = 'block';
};
const enablePlugin = async () => {
homebridge.showSpinner();
document.getElementById('disabledBanner').style.display = 'none';
currentConfig[0].disablePlugin = false;
await homebridge.updatePluginConfig(currentConfig);
await homebridge.savePluginConfig();
homebridge.hideSpinner();
};
document.getElementById('menuHome').addEventListener('click', () => showSupport());
document.getElementById('menuDevices').addEventListener('click', () => showDevices());
document.getElementById('menuLocation').addEventListener('click', () => showLocation());
document.getElementById('menuSettings').addEventListener('click', () => showSettings());
document.getElementById('disabledEnable').addEventListener('click', () => enablePlugin());
if (currentConfig.length) {
document.getElementById('menuWrapper').style.display = 'inline-flex';
showLocation(); // Set Location as the default tab
if (currentConfig[0].disablePlugin) {
showDisabledBanner();
}
} else {
currentConfig.push({ name: 'Air' });
await homebridge.updatePluginConfig(currentConfig);
showIntro();
}
} catch (err) {
homebridge.toast.error(err.message, 'Error');
} finally {
homebridge.hideSpinner();
}
})();
</script>