UNPKG

3.88 kBJavaScriptView Raw
1import Logger from 'nightingale/src';
2import { hostname } from 'os';
3import createSocketClient from 'socket.io-client';
4import { serverHost, serverPort, token, device } from './params';
5import { getTime as getConfigTime } from './config';
6import { onConfigUpdated } from './manager';
7import * as screen from './commands/screen';
8import * as display from './commands/display';
9import availableDisplays from './utils/availableDisplays';
10import findNetworkInterface from './utils/networkInterface';
11import { selfUpdate } from './update';
12import pkg from '../../package.json';
13import { runSync } from './utils/exec';
14
15const logger = new Logger('app:client');
16
17const socket =
18 serverHost &&
19 serverPort &&
20 createSocketClient(`${serverHost}:${serverPort}/raspberry-client`, {
21 autoConnect: false,
22 reconnection: true,
23 reconnectionDelay: 500,
24 reconnectionDelayMax: 120000, // 2 minutes
25 reconnectionAttempts: Infinity,
26 timeout: 4000,
27 transports: ['websocket'],
28 });
29
30const emit = (eventName: string, ...args: Array<any>) => {
31 if (!socket) {
32 logger.warn('cannot emit', { eventName, args });
33 return;
34 }
35
36 logger.debug('emit', { eventName, args });
37 return socket.emit(eventName, ...args);
38};
39
40export const sendUpdate = (data: Object): void => {
41 emit('update', data);
42};
43
44if (socket) {
45 // wait 1s before connecting
46 setTimeout(() => {
47 logger.debug('Connecting', { serverHost, serverPort });
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 client: { name: pkg.name, version: pkg.version },
67 token,
68 screenState, // deprecated
69 ...networkInterface,
70 hostname: hostname(),
71 device,
72 screen: {
73 state: screenState,
74 screens: screen.getCurrentScreens(),
75 },
76 availableDisplays,
77 });
78 });
79
80 socket.on('updateConfig', onConfigUpdated);
81 socket.on('changeConfig', onConfigUpdated);
82
83 socket.on('selfUpdate', () => selfUpdate());
84
85 socket.on('action', (action: string) => {
86 logger.info('received action', { action });
87 switch (action) {
88 case 'self-upgrade':
89 case 'self-update':
90 case 'selfUpdate':
91 return selfUpdate();
92
93 case 'screen-off':
94 return screen.off();
95 case 'screen-on':
96 return screen.on();
97
98 case 'refresh':
99 return display.refresh();
100
101 case 'reboot':
102 sendUpdate({ rebooting: true });
103 display.stop();
104 return runSync('reboot');
105
106 case 'poweroff':
107 sendUpdate({ rebooting: true });
108 display.stop();
109 return runSync('poweroff');
110 }
111
112 logger.warn(`unknown action: ${action}`);
113 });
114
115 socket.on('poll-data', () => {
116 logger.debug('poll data');
117 const screenshotBuffer = screen.screenshot();
118 if (!screenshotBuffer) {
119 return;
120 }
121
122 logger.debug('send screenshot');
123 socket.emit('update-data', { screenshotBuffer });
124 });
125
126 socket.connect();
127 }, 1000);
128}
129
130export function close(): Promise<any> | void {
131 if (!socket || !socket.connected) {
132 return;
133 }
134
135 return new Promise(resolve => {
136 logger.info('Closing...');
137 socket.once('disconnect', () => {
138 logger.info('Closed');
139 resolve();
140 });
141 socket.close();
142 });
143}