import {css, html, LitElement} from 'lit'; import {customElement, property} from 'lit/decorators.js'; import {live} from 'lit/directives/live.js'; import {styleMap} from 'lit/directives/style-map.js'; import {Device, Notifiable, SimulationInfo, simulationState,} from './device-observer.js'; import {State} from './model.js' @customElement('ns-device-info') export class DeviceInformation extends LitElement implements Notifiable { // Selected Device on scene @property() selectedDevice: Device|undefined; /** * the yaw value in orientation for ns-cube-sprite * unit: deg */ @property({type : Number}) yaw = 0; /** * the pitch value in orientation for ns-cube-spriteß * unit: deg */ @property({type : Number}) pitch = 0; /** * the roll value in orientation for ns-cube-sprite * unit: deg */ @property({type : Number}) roll = 0; /** * The state of device info. True if edit mode. */ @property({type : Boolean}) editMode = false; /** * the x value in position for ns-cube-sprite * unit: cm */ @property({type : Number}) posX = 0; /** * the y value in position for ns-cube-sprite * unit: cm */ @property({type : Number}) posY = 0; /** * the z value in position for ns-cube-sprite * unit: cm */ @property({type : Number}) posZ = 0; holdRange = false; static styles = css` :host { cursor: pointer; display: grid; place-content: center; color: white; font-size: 25px; font-family: 'Lato', sans-serif; border: 5px solid black; border-radius: 12px; padding: 10px; background-color: #9199a5; max-width: 600px; } .title { font-weight: bold; text-transform: uppercase; text-align: center; margin-bottom: 10px; } .setting { display: grid; grid-template-columns: auto auto; margin-top: 0px; margin-bottom: 30px; //border: 3px solid black; padding: 10px; } .setting .name { grid-column: 1 / span 2; text-transform: uppercase; text-align: left; margin-bottom: 10px; font-weight: bold; } .label { grid-column: 1; text-align: left; } .info { grid-column: 2; text-align: right; margin-bottom: 10px; } .switch { position: relative; float: right; width: 60px; height: 34px; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; -webkit-transition: 0.4s; transition: 0.4s; } .slider:before { position: absolute; content: ''; height: 26px; width: 26px; left: 4px; bottom: 4px; background-color: white; -webkit-transition: 0.4s; transition: 0.4s; } input:checked + .slider { background-color: #2196f3; } input:focus + .slider { box-shadow: 0 0 1px #2196f3; } input:checked + .slider:before { -webkit-transform: translateX(26px); -ms-transform: translateX(26px); transform: translateX(26px); } /* Rounded sliders */ .slider.round { border-radius: 34px; } .slider.round:before { border-radius: 50%; } .text { display: inline-block; position: relative; width: 50px; } input[type='range'] { width: 400px; } input[type='text'] { width: 50%; font-size: inherit; text-align: right; max-height: 25px; } input[type='text'].orientation { max-width: 50px; } input[type='button'] { display: inline; font-size: inherit; max-width: 200px; } `; connectedCallback() { super.connectedCallback(); // eslint-disable-line simulationState.registerObserver(this); } disconnectedCallback() { simulationState.removeObserver(this); super.disconnectedCallback(); // eslint-disable-line } onNotify(data: SimulationInfo) { if (data.selectedId && this.editMode === false) { for (const device of data.devices) { if (device.name === data.selectedId) { this.selectedDevice = device; if (!this.holdRange){ this.yaw = device.orientation.yaw; this.pitch = device.orientation.pitch; this.roll = device.orientation.roll; } this.posX = Math.floor(device.position.x * 100); this.posY = Math.floor(device.position.y * 100); this.posZ = Math.floor(device.position.z * 100); break; } } } } private changeRange(ev: InputEvent) { this.holdRange = true; console.assert(this.selectedDevice !== null); // eslint-disable-line const range = ev.target as HTMLInputElement; const event = new CustomEvent('orientationEvent', { detail: { name: this.selectedDevice?.name, type: range.id, value: range.value, }, }); window.dispatchEvent(event); if (range.id === 'yaw') { this.yaw = Number(range.value); } else if (range.id === 'pitch') { this.pitch = Number(range.value); } else { this.roll = Number(range.value); } } private patchOrientation() { this.holdRange = false; console.assert(this.selectedDevice !== undefined); // eslint-disable-line if (this.selectedDevice === undefined) return; this.selectedDevice.orientation = {yaw: this.yaw, pitch: this.pitch, roll: this.roll}; simulationState.patchDevice({ device: { name: this.selectedDevice.name, orientation: this.selectedDevice.orientation, }, }); } private patchRadio() { console.assert(this.selectedDevice !== undefined); // eslint-disable-line if (this.selectedDevice === undefined) return; simulationState.patchDevice({ device: { name: this.selectedDevice.name, chips: this.selectedDevice.chips, }, }); } private handleEditForm() { if (this.editMode) { simulationState.invokeGetDevice(); this.editMode = false; } else { this.editMode = true; } } static checkPositionBound(value: number) { return value > 10 ? 10 : value < 0 ? 0 : value; // eslint-disable-line } static checkOrientationBound(value: number) { return value > 90 ? 90 : value < -90 ? -90 : value; // eslint-disable-line } private handleSave() { console.assert(this.selectedDevice !== undefined); // eslint-disable-line if (this.selectedDevice === undefined) return; const elements = this.renderRoot.querySelectorAll(`[id^="edit"]`); const obj: Record = { name: this.selectedDevice.name, position: this.selectedDevice.position, orientation: this.selectedDevice.orientation, }; elements.forEach(element => { const inputElement = element as HTMLInputElement; if (inputElement.id === 'editName') { obj.name = inputElement.value; } else if (inputElement.id.startsWith('editPos')) { if (!Number.isNaN(Number(inputElement.value))) { obj.position[inputElement.id.slice(7).toLowerCase()] = DeviceInformation.checkPositionBound( Number(inputElement.value) / 100 ); } } else if (inputElement.id.startsWith('editOri')) { if (!Number.isNaN(Number(inputElement.value))) { obj.orientation[inputElement.id.slice(7).toLowerCase()] = DeviceInformation.checkOrientationBound(Number(inputElement.value)); } } }); this.selectedDevice.name = obj.name; this.selectedDevice.position = obj.position; this.selectedDevice.orientation = obj.orientation; this.handleEditForm(); simulationState.patchDevice({ device: obj, }); } private handleGetChips() { const disabledCheckbox = html` `; let lowEnergyCheckbox = disabledCheckbox; let classicCheckbox = disabledCheckbox; let wifiCheckbox = disabledCheckbox; let uwbCheckbox = disabledCheckbox; if (this.selectedDevice) { if ('chips' in this.selectedDevice && this.selectedDevice.chips) { for (const chip of this.selectedDevice.chips) { if ('bt' in chip && chip.bt) { if ('lowEnergy' in chip.bt && chip.bt.lowEnergy && 'state' in chip.bt.lowEnergy) { lowEnergyCheckbox = html ` { // eslint-disable-next-line this.selectedDevice?.toggleChipState(chip, 'lowEnergy'); this.patchRadio(); }} /> `; } if ('classic' in chip.bt && chip.bt.classic && 'state' in chip.bt.classic) { classicCheckbox = html` { // eslint-disable-next-line this.selectedDevice?.toggleChipState(chip, 'classic'); this.patchRadio(); }} /> `; } } if ('wifi' in chip && chip.wifi) { wifiCheckbox = html` { // eslint-disable-next-line this.selectedDevice?.toggleChipState(chip); this.patchRadio(); }} /> `; } if ('uwb' in chip && chip.uwb) { uwbCheckbox = html` { // eslint-disable-next-line this.selectedDevice?.toggleChipState(chip); this.patchRadio(); }} /> `; } } } } return html` BLE ${lowEnergyCheckbox} Classic ${classicCheckbox} WIFI ${wifiCheckbox} UWB ${uwbCheckbox} `; } render() { return html`${this.selectedDevice ? html` Device Info Name ${this.selectedDevice.name} Position X ${this.editMode ? html`` : html`${this.posX}`} Y ${this.editMode ? html`` : html`${this.posY}`} Z ${this.editMode ? html`` : html`${this.posZ}`} Orientation Yaw ${this.editMode ? html`` : html`(${this.yaw})`} Pitch ${this.editMode ? html`` : html`(${this.pitch})`} Roll ${this.editMode ? html`` : html`(${this.roll})`} ${this.editMode ? html` ` : html``} Radio States ${this.handleGetChips()} ` : html`Device Info`}`; }}