xref: /aosp_15_r20/tools/netsim/ui/ts/device-map.ts (revision cf78ab8cffb8fc9207af348f23af247fb04370a6)
1*cf78ab8cSAndroid Build Coastguard Workerimport {css, html, LitElement} from 'lit';
2*cf78ab8cSAndroid Build Coastguard Workerimport {customElement, property} from 'lit/decorators.js';
3*cf78ab8cSAndroid Build Coastguard Workerimport {styleMap} from 'lit/directives/style-map.js';
4*cf78ab8cSAndroid Build Coastguard Worker
5*cf78ab8cSAndroid Build Coastguard Workerimport {Device, Notifiable, SimulationInfo, simulationState,} from './device-observer.js';
6*cf78ab8cSAndroid Build Coastguard Worker
7*cf78ab8cSAndroid Build Coastguard Worker@customElement('ns-device-map')
8*cf78ab8cSAndroid Build Coastguard Workerexport class DeviceMap extends LitElement implements Notifiable {
9*cf78ab8cSAndroid Build Coastguard Worker  /**
10*cf78ab8cSAndroid Build Coastguard Worker   * List of devices currently on the netsim.
11*cf78ab8cSAndroid Build Coastguard Worker   */
12*cf78ab8cSAndroid Build Coastguard Worker  @property() deviceData: Device[] = [];
13*cf78ab8cSAndroid Build Coastguard Worker
14*cf78ab8cSAndroid Build Coastguard Worker  /**
15*cf78ab8cSAndroid Build Coastguard Worker   * Index of the background image displayed.
16*cf78ab8cSAndroid Build Coastguard Worker   */
17*cf78ab8cSAndroid Build Coastguard Worker  @property() imageIdx = 0;
18*cf78ab8cSAndroid Build Coastguard Worker
19*cf78ab8cSAndroid Build Coastguard Worker  /**
20*cf78ab8cSAndroid Build Coastguard Worker   * Number of images available for the background.
21*cf78ab8cSAndroid Build Coastguard Worker   */
22*cf78ab8cSAndroid Build Coastguard Worker  @property() numImages = 3;
23*cf78ab8cSAndroid Build Coastguard Worker
24*cf78ab8cSAndroid Build Coastguard Worker  @property({type: Boolean, reflect: true}) isometric: boolean = false;
25*cf78ab8cSAndroid Build Coastguard Worker
26*cf78ab8cSAndroid Build Coastguard Worker  connectedCallback() {
27*cf78ab8cSAndroid Build Coastguard Worker    super.connectedCallback();  // eslint-disable-line
28*cf78ab8cSAndroid Build Coastguard Worker    simulationState.registerObserver(this);
29*cf78ab8cSAndroid Build Coastguard Worker    window.addEventListener('map-button-clicked', this.onChangeMap);
30*cf78ab8cSAndroid Build Coastguard Worker    window.addEventListener(
31*cf78ab8cSAndroid Build Coastguard Worker        'isometric-button-clicked', this.handleIsometricView);
32*cf78ab8cSAndroid Build Coastguard Worker  }
33*cf78ab8cSAndroid Build Coastguard Worker
34*cf78ab8cSAndroid Build Coastguard Worker  disconnectedCallback() {
35*cf78ab8cSAndroid Build Coastguard Worker    window.removeEventListener(
36*cf78ab8cSAndroid Build Coastguard Worker        'isometric-button-clicked', this.handleIsometricView);
37*cf78ab8cSAndroid Build Coastguard Worker    window.removeEventListener('map-button-clicked', this.onChangeMap);
38*cf78ab8cSAndroid Build Coastguard Worker    simulationState.removeObserver(this);
39*cf78ab8cSAndroid Build Coastguard Worker    super.disconnectedCallback();  // eslint-disable-line
40*cf78ab8cSAndroid Build Coastguard Worker  }
41*cf78ab8cSAndroid Build Coastguard Worker
42*cf78ab8cSAndroid Build Coastguard Worker  static styles = css`
43*cf78ab8cSAndroid Build Coastguard Worker    #dropzone {
44*cf78ab8cSAndroid Build Coastguard Worker      margin-left: 200px;
45*cf78ab8cSAndroid Build Coastguard Worker      margin-right: 200px;
46*cf78ab8cSAndroid Build Coastguard Worker      transition: transform 2s, top 2s;
47*cf78ab8cSAndroid Build Coastguard Worker      transform-style: preserve-3d;
48*cf78ab8cSAndroid Build Coastguard Worker    }
49*cf78ab8cSAndroid Build Coastguard Worker
50*cf78ab8cSAndroid Build Coastguard Worker    .box {
51*cf78ab8cSAndroid Build Coastguard Worker      position: relative;
52*cf78ab8cSAndroid Build Coastguard Worker      width: 1000px; //40vw;
53*cf78ab8cSAndroid Build Coastguard Worker      height: 1000px; //40vh;
54*cf78ab8cSAndroid Build Coastguard Worker      border: solid 1px rgb(198, 210, 255);
55*cf78ab8cSAndroid Build Coastguard Worker      margin: 2.5em auto;
56*cf78ab8cSAndroid Build Coastguard Worker    }
57*cf78ab8cSAndroid Build Coastguard Worker
58*cf78ab8cSAndroid Build Coastguard Worker    .pattern0 {
59*cf78ab8cSAndroid Build Coastguard Worker      background-image: url(./assets/grid-background.svg);
60*cf78ab8cSAndroid Build Coastguard Worker    }
61*cf78ab8cSAndroid Build Coastguard Worker
62*cf78ab8cSAndroid Build Coastguard Worker    .pattern1 {
63*cf78ab8cSAndroid Build Coastguard Worker      background-image: url(./assets/polar-background.svg);
64*cf78ab8cSAndroid Build Coastguard Worker      background-size: 1150px 1150px;
65*cf78ab8cSAndroid Build Coastguard Worker      background-position: center;
66*cf78ab8cSAndroid Build Coastguard Worker    }
67*cf78ab8cSAndroid Build Coastguard Worker
68*cf78ab8cSAndroid Build Coastguard Worker    .pattern2 {
69*cf78ab8cSAndroid Build Coastguard Worker      background-image: url(./assets/hexagonal-background.png);
70*cf78ab8cSAndroid Build Coastguard Worker      background-size: 1175px 1175px;
71*cf78ab8cSAndroid Build Coastguard Worker      background-position: center;
72*cf78ab8cSAndroid Build Coastguard Worker    }
73*cf78ab8cSAndroid Build Coastguard Worker
74*cf78ab8cSAndroid Build Coastguard Worker    .container {
75*cf78ab8cSAndroid Build Coastguard Worker      display: flex;
76*cf78ab8cSAndroid Build Coastguard Worker      width: 100%;
77*cf78ab8cSAndroid Build Coastguard Worker    }
78*cf78ab8cSAndroid Build Coastguard Worker
79*cf78ab8cSAndroid Build Coastguard Worker    .contentA {
80*cf78ab8cSAndroid Build Coastguard Worker      flex: 2;
81*cf78ab8cSAndroid Build Coastguard Worker    }
82*cf78ab8cSAndroid Build Coastguard Worker
83*cf78ab8cSAndroid Build Coastguard Worker    .contentB {
84*cf78ab8cSAndroid Build Coastguard Worker      flex: 2;
85*cf78ab8cSAndroid Build Coastguard Worker    }
86*cf78ab8cSAndroid Build Coastguard Worker
87*cf78ab8cSAndroid Build Coastguard Worker    ns-device-dragzone {
88*cf78ab8cSAndroid Build Coastguard Worker      transform-style: inherit;
89*cf78ab8cSAndroid Build Coastguard Worker    }
90*cf78ab8cSAndroid Build Coastguard Worker  `;
91*cf78ab8cSAndroid Build Coastguard Worker
92*cf78ab8cSAndroid Build Coastguard Worker  onNotify(data: SimulationInfo): void {
93*cf78ab8cSAndroid Build Coastguard Worker    this.deviceData = data.devices;
94*cf78ab8cSAndroid Build Coastguard Worker    this.requestUpdate();
95*cf78ab8cSAndroid Build Coastguard Worker  }
96*cf78ab8cSAndroid Build Coastguard Worker
97*cf78ab8cSAndroid Build Coastguard Worker  private onChangeMap = () => {
98*cf78ab8cSAndroid Build Coastguard Worker    this.imageIdx = (this.imageIdx + 1) % this.numImages;
99*cf78ab8cSAndroid Build Coastguard Worker  };
100*cf78ab8cSAndroid Build Coastguard Worker
101*cf78ab8cSAndroid Build Coastguard Worker  private handleIsometricView = () => {
102*cf78ab8cSAndroid Build Coastguard Worker    this.isometric = !this.isometric;
103*cf78ab8cSAndroid Build Coastguard Worker  };
104*cf78ab8cSAndroid Build Coastguard Worker
105*cf78ab8cSAndroid Build Coastguard Worker  checkBle(device: Device):
106*cf78ab8cSAndroid Build Coastguard Worker      boolean{return device.chips.at(0)?.bleBeacon !== undefined}
107*cf78ab8cSAndroid Build Coastguard Worker
108*cf78ab8cSAndroid Build Coastguard Worker  render() {
109*cf78ab8cSAndroid Build Coastguard Worker    const rainbow = [
110*cf78ab8cSAndroid Build Coastguard Worker      'red',
111*cf78ab8cSAndroid Build Coastguard Worker      'orange',
112*cf78ab8cSAndroid Build Coastguard Worker      'yellow',
113*cf78ab8cSAndroid Build Coastguard Worker      'green',
114*cf78ab8cSAndroid Build Coastguard Worker      'blue',
115*cf78ab8cSAndroid Build Coastguard Worker      'indigo',
116*cf78ab8cSAndroid Build Coastguard Worker      'purple',
117*cf78ab8cSAndroid Build Coastguard Worker    ];
118*cf78ab8cSAndroid Build Coastguard Worker    const viewStyle = this.isometric ?
119*cf78ab8cSAndroid Build Coastguard Worker        `perspective(200rem) rotateX(60deg) rotateY(0deg) rotateZ(0deg) scale3d(0.8,0.8,0.8); top: 250px` :
120*cf78ab8cSAndroid Build Coastguard Worker        'none; top: 0px;';
121*cf78ab8cSAndroid Build Coastguard Worker
122*cf78ab8cSAndroid Build Coastguard Worker    return html`
123*cf78ab8cSAndroid Build Coastguard Worker      <ns-device-dropzone role="widget" tabindex="0" aria-label="Device map">
124*cf78ab8cSAndroid Build Coastguard Worker        <div id="dropzone" class="box pattern${this.imageIdx}">
125*cf78ab8cSAndroid Build Coastguard Worker          ${
126*cf78ab8cSAndroid Build Coastguard Worker        this.deviceData.map(
127*cf78ab8cSAndroid Build Coastguard Worker            (device, idx) => html`
128*cf78ab8cSAndroid Build Coastguard Worker              ${
129*cf78ab8cSAndroid Build Coastguard Worker                true ?  // TODO manage device.visible in Web UI
130*cf78ab8cSAndroid Build Coastguard Worker                    this.checkBle(device) ?
131*cf78ab8cSAndroid Build Coastguard Worker                    html`
132*cf78ab8cSAndroid Build Coastguard Worker                    <ns-device-dragzone
133*cf78ab8cSAndroid Build Coastguard Worker                      .action=${'move'}
134*cf78ab8cSAndroid Build Coastguard Worker                      style=${styleMap({
135*cf78ab8cSAndroid Build Coastguard Worker                      position: 'absolute',
136*cf78ab8cSAndroid Build Coastguard Worker                      left: `${device.position.x * 100}px`,
137*cf78ab8cSAndroid Build Coastguard Worker                      top: `${device.position.y * 100}px`,
138*cf78ab8cSAndroid Build Coastguard Worker                    })}
139*cf78ab8cSAndroid Build Coastguard Worker                    >
140*cf78ab8cSAndroid Build Coastguard Worker                      <ns-pyramid-sprite
141*cf78ab8cSAndroid Build Coastguard Worker                        id=${device.name}
142*cf78ab8cSAndroid Build Coastguard Worker                        .color=${rainbow[idx % rainbow.length]}
143*cf78ab8cSAndroid Build Coastguard Worker                        .size=${'30px'}
144*cf78ab8cSAndroid Build Coastguard Worker                        .controls=${true}
145*cf78ab8cSAndroid Build Coastguard Worker                        yaw=${device.orientation.yaw}
146*cf78ab8cSAndroid Build Coastguard Worker                        pitch=${device.orientation.pitch}
147*cf78ab8cSAndroid Build Coastguard Worker                        roll=${device.orientation.roll}
148*cf78ab8cSAndroid Build Coastguard Worker                        posZ=${device.position.z * 100}
149*cf78ab8cSAndroid Build Coastguard Worker                        role="widget"
150*cf78ab8cSAndroid Build Coastguard Worker                        tabindex="1"
151*cf78ab8cSAndroid Build Coastguard Worker                        aria-label="${device.name} on Device Map, Position: ${
152*cf78ab8cSAndroid Build Coastguard Worker                        Math.round(device.position.x * 100)}, ${
153*cf78ab8cSAndroid Build Coastguard Worker                        Math.round(device.position.y * 100)}, ${
154*cf78ab8cSAndroid Build Coastguard Worker                        Math.round(
155*cf78ab8cSAndroid Build Coastguard Worker                            device.position.z * 100)}, Orientation: yaw: ${
156*cf78ab8cSAndroid Build Coastguard Worker                        device.orientation.yaw}, pitch: ${
157*cf78ab8cSAndroid Build Coastguard Worker                        device.orientation.pitch}, roll: ${
158*cf78ab8cSAndroid Build Coastguard Worker                        device.orientation.roll}"
159*cf78ab8cSAndroid Build Coastguard Worker                        aria-live="polite"
160*cf78ab8cSAndroid Build Coastguard Worker                      ></ns-pyramid-sprite>
161*cf78ab8cSAndroid Build Coastguard Worker                    </ns-device-dragzone>
162*cf78ab8cSAndroid Build Coastguard Worker                  ` :
163*cf78ab8cSAndroid Build Coastguard Worker                    html`
164*cf78ab8cSAndroid Build Coastguard Worker                  <ns-device-dragzone
165*cf78ab8cSAndroid Build Coastguard Worker                    .action=${'move'}
166*cf78ab8cSAndroid Build Coastguard Worker                    style=${styleMap({
167*cf78ab8cSAndroid Build Coastguard Worker                      position: 'absolute',
168*cf78ab8cSAndroid Build Coastguard Worker                      left: `${device.position.x * 100}px`,
169*cf78ab8cSAndroid Build Coastguard Worker                      top: `${device.position.y * 100}px`,
170*cf78ab8cSAndroid Build Coastguard Worker                    })}
171*cf78ab8cSAndroid Build Coastguard Worker                  >
172*cf78ab8cSAndroid Build Coastguard Worker                    <ns-cube-sprite
173*cf78ab8cSAndroid Build Coastguard Worker                      id=${device.name}
174*cf78ab8cSAndroid Build Coastguard Worker                      .color=${rainbow[idx % rainbow.length]}
175*cf78ab8cSAndroid Build Coastguard Worker                      .size=${'30px'}
176*cf78ab8cSAndroid Build Coastguard Worker                      .controls=${true}
177*cf78ab8cSAndroid Build Coastguard Worker                      yaw=${device.orientation.yaw}
178*cf78ab8cSAndroid Build Coastguard Worker                      pitch=${device.orientation.pitch}
179*cf78ab8cSAndroid Build Coastguard Worker                      roll=${device.orientation.roll}
180*cf78ab8cSAndroid Build Coastguard Worker                      posZ=${device.position.z * 100}
181*cf78ab8cSAndroid Build Coastguard Worker                      role="widget"
182*cf78ab8cSAndroid Build Coastguard Worker                      tabindex="1"
183*cf78ab8cSAndroid Build Coastguard Worker                      aria-label="${device.name} on Device Map, Position: ${
184*cf78ab8cSAndroid Build Coastguard Worker                        Math.round(device.position.x * 100)}, ${
185*cf78ab8cSAndroid Build Coastguard Worker                        Math.round(device.position.y * 100)}, ${
186*cf78ab8cSAndroid Build Coastguard Worker                        Math.round(
187*cf78ab8cSAndroid Build Coastguard Worker                            device.position.z * 100)}, Orientation: yaw: ${
188*cf78ab8cSAndroid Build Coastguard Worker                        device.orientation.yaw}, pitch: ${
189*cf78ab8cSAndroid Build Coastguard Worker                        device.orientation.pitch}, roll: ${
190*cf78ab8cSAndroid Build Coastguard Worker                        device.orientation.roll}"
191*cf78ab8cSAndroid Build Coastguard Worker                      aria-live="polite"
192*cf78ab8cSAndroid Build Coastguard Worker                    ></ns-cube-sprite>
193*cf78ab8cSAndroid Build Coastguard Worker                  </ns-device-dragzone>
194*cf78ab8cSAndroid Build Coastguard Worker                ` :
195*cf78ab8cSAndroid Build Coastguard Worker                    html``}
196*cf78ab8cSAndroid Build Coastguard Worker            `)}
197*cf78ab8cSAndroid Build Coastguard Worker        </div>
198*cf78ab8cSAndroid Build Coastguard Worker        <style>
199*cf78ab8cSAndroid Build Coastguard Worker          #dropzone {
200*cf78ab8cSAndroid Build Coastguard Worker            transform: ${viewStyle};
201*cf78ab8cSAndroid Build Coastguard Worker          }
202*cf78ab8cSAndroid Build Coastguard Worker        </style>
203*cf78ab8cSAndroid Build Coastguard Worker      </ns-device-dropzone>
204*cf78ab8cSAndroid Build Coastguard Worker    `;
205*cf78ab8cSAndroid Build Coastguard Worker  }
206*cf78ab8cSAndroid Build Coastguard Worker}
207