1 | import Logger from 'nightingale';
|
2 | import { hostname } from 'os';
|
3 | import createSocketClient from 'socket.io-client';
|
4 | import { serverHost, serverPort, token } from './argv';
|
5 | import { getTime as getConfigTime } from './config';
|
6 | import { onConfigUpdated } from './manager';
|
7 | import * as display from './commands/display';
|
8 | import * as screen from './commands/screen';
|
9 | import findNetworkInterface from './utils/networkInterface';
|
10 | import detectBoard from './utils/detectBoard';
|
11 | import { selfUpdate } from './update';
|
12 | import { version } from '../package.json';
|
13 |
|
14 | const logger = new Logger('app:client');
|
15 |
|
16 | const socket =
|
17 | serverHost &&
|
18 | serverPort &&
|
19 | createSocketClient(`${serverHost}:${serverPort}/raspberry-client`, {
|
20 | reconnectionDelay: 500,
|
21 | reconnectionDelayMax: 120000,
|
22 | timeout: 4000,
|
23 | transports: ['websocket'],
|
24 | });
|
25 |
|
26 |
|
27 | setTimeout(() => {
|
28 | logger.debug('Connecting', { serverHost, serverPort });
|
29 | if (socket) {
|
30 | socket.connect();
|
31 | }
|
32 | }, 5000);
|
33 |
|
34 | const board = detectBoard();
|
35 | const rpiVersion = board === 'rpi' && board.info;
|
36 |
|
37 | const emit = (eventName: string, ...args: Array<any>) => {
|
38 | if (!socket) {
|
39 | logger.warn('cannot emit', { eventName, args });
|
40 | return;
|
41 | }
|
42 |
|
43 | logger.debug('emit', { eventName, args });
|
44 | return socket.emit(eventName, ...args);
|
45 | };
|
46 |
|
47 | if (socket) {
|
48 | socket.on('connect_error', err =>
|
49 | logger.error('connect error', { serverHost, serverPort, errMessage: err.message }),
|
50 | );
|
51 | socket.on('reconnect_error', err =>
|
52 | logger.debug('reconnect error', { serverHost, serverPort, err }),
|
53 | );
|
54 |
|
55 | socket.on('disconnect', () => logger.warn('disconnected'));
|
56 |
|
57 | socket.on('reconnect', () => logger.success('reconnected'));
|
58 |
|
59 | socket.on('connect', () => {
|
60 | logger.success('connected');
|
61 |
|
62 | const networkInterface = findNetworkInterface();
|
63 | const screenState = screen.getCurrentScreenState();
|
64 | emit('hello', {
|
65 | configTime: getConfigTime(),
|
66 | version,
|
67 | token,
|
68 | userId: token,
|
69 | screenState,
|
70 | ...networkInterface,
|
71 | hostname: hostname(),
|
72 | rpiVersion,
|
73 | board,
|
74 | screen: {
|
75 | state: screenState,
|
76 | screens: screen.getCurrentScreens(),
|
77 | },
|
78 | availableDisplays: display.availableDisplays,
|
79 | });
|
80 | });
|
81 |
|
82 | socket.on('updateConfig', onConfigUpdated);
|
83 | socket.on('changeConfig', onConfigUpdated);
|
84 |
|
85 | socket.on('selfUpdate', () => selfUpdate());
|
86 |
|
87 | socket.on('action', (action: string) => {
|
88 | logger.info('received action', { action });
|
89 | switch (action) {
|
90 | case 'self-upgrade':
|
91 | case 'self-update':
|
92 | case 'selfUpdate':
|
93 | return selfUpdate();
|
94 |
|
95 | case 'screen-off':
|
96 | return screen.off();
|
97 | case 'screen-on':
|
98 | return screen.on();
|
99 |
|
100 | case 'refresh':
|
101 | return display.refresh();
|
102 | }
|
103 |
|
104 | logger.warn(`unknown action: ${action}`);
|
105 | });
|
106 |
|
107 | socket.on('screenshot', () => {
|
108 | logger.info('screenshot');
|
109 | const buffer = screen.screenshot();
|
110 | if (!buffer) {
|
111 | return;
|
112 | }
|
113 |
|
114 | logger.info('send screenshot');
|
115 | socket.emit('screenshot', { image: true, buffer }, () => {
|
116 | logger.info('screenshot callback');
|
117 | });
|
118 | });
|
119 | }
|
120 |
|
121 | export const sendUpdate = (data: Object): void => {
|
122 | emit('update', data);
|
123 | };
|
124 |
|
125 | export function close(): Promise<any> | void {
|
126 | if (!socket || !socket.connected) {
|
127 | return;
|
128 | }
|
129 |
|
130 | return new Promise(resolve => {
|
131 | logger.info('Closing...');
|
132 | socket.once('disconnect', () => {
|
133 | logger.info('Closed');
|
134 | resolve();
|
135 | });
|
136 | socket.close();
|
137 | });
|
138 | }
|