-
Notifications
You must be signed in to change notification settings - Fork 2
/
ser2bt_status
executable file
·399 lines (346 loc) · 15.7 KB
/
ser2bt_status
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
#!/usr/bin/python3
# -*- coding:utf-8 -*-
#import modules
import os #hostname
import sys #check python version.
import time #timers for sleep
import configparser #to handle the config file.
try:
from waveshare_epd import epd2in13_V2
from PIL import Image, ImageDraw, ImageFont # Font handeling
except:
print ("No Waveshare e-ink was detected. Please investigate, and try again\n")
exit()
try:
import netifaces #get active interface (wlan)
import psutil # Capture cpu and memory values
import syslog
import subprocess #get ssid
import signal # Check for incomming signals from the service and react if there is term signal.
except:
print ("No supporing system/network libraries were detected. Please investigate, and try again\n")
exit()
#import configuration file:
#Read ser2bt_config.ini file
config_obj = configparser.ConfigParser()
config_obj.read("/etc/ser2bt_config.ini")
screen = config_obj["screen"]
# parameters to use the keys from the ser2bt_config.ini
screen_rotate = int(screen["screen_rotate"])
foreground = int(screen["foreground"])
background = int(screen["background"])
# Variable decleration:
sys.path.append(r'lib')
epd = epd2in13_V2.EPD()
host_name=os.uname()[1] # define host_name
dev_dir='/dev/'
tmp_dir='/tmp/'
bat_file='bat'
shut_file = 'shut'
bt_ser_short_label='BT'
bt_ser_label='rfcomm0'
bt_ser_port=bt_ser_label
usb_ser_label='USB'
usb_ser_port='tty'+usb_ser_label
acm_ser_label='ACM'
acm_ser_port='tty'+acm_ser_label
picdir='/usr/local/lib/ser2bt-bridge/images/'
roboto_font_dir='/usr/share/fonts/truetype/roboto/unhinted/RobotoTTF/'
dejavu_font_dir='/usr/share/fonts/truetype/dejavu/'
end_of_loop_pause = 30 #sleep time in seconds. Will be used at the end of the loop so as not to kill the cpu.
full_tty_status = "No tty Connections"
old_ssid = "XX"
old_host_ip = "XX"
old_lan_status = "XX"
old_bt_status = "XX"
old_full_tty_status = "XX"
old_bt_serial_port = "XX"
old_total_serial_lines = "XX"
inactive = "inactive"
active = "active"
not_connected = "Not Connected"
#Declare the fonts to be used:
f_title_font18 = ImageFont.truetype(roboto_font_dir+'Roboto-Bold.ttf', 18)
f_var_spc_char_font18 = ImageFont.truetype(dejavu_font_dir+'DejaVuSans-Bold.ttf', 18)
f_title_font24 = ImageFont.truetype(roboto_font_dir+'Roboto-Medium.ttf', 24)
f_var_font18 = ImageFont.truetype(roboto_font_dir+'Roboto-Medium.ttf', 18)
f_top_line_font16 = ImageFont.truetype(roboto_font_dir+'Roboto-Medium.ttf', 16)
#Setup logging: Work in progress
syslog.openlog(ident="ser2bt-bridge",logoption=syslog.LOG_PID, facility=syslog.LOG_LOCAL7)
syslog.syslog(syslog.LOG_INFO, 'ser2bt_status was started')
#Put the display into sleep
epd.init(epd.FULL_UPDATE)
epd.sleep()
#Define the functions:
###################################################################################################################
def set_shutdown_flag(intent):
power_off = 'p'
exit_out = 'e'
file = open(tmp_dir+shut_file,'w')
file.write(intent)
file.close()
if intent == power_off:
msg = 'Shutdown'
else:
msg = 'No Shutdown'
return (msg)
def bat_lvl():
f = open(tmp_dir+bat_file,'r')
bat = f.read()
f.close()
if bat == "":
bat="Err"
return (bat)
def handler(signum, frame):
syslog.syslog(syslog.LOG_ERR, 'Got SIGTERM!')
sys.exit(0) # raises a SystemExit exception
def get_bt_service_status():
global old_bt_status
bt_services = [ 'bluetooth', 'hciuart', 'rfcomm' ]
inactive = 'inactive' #for loop to cycle through the three bluetooth-related services to check their status.
for counter, bt_service in enumerate(bt_services, start=1):
active_counter = counter
bt_service = subprocess.Popen(['systemctl', 'is-active', bt_service], stdout=subprocess.PIPE).communicate()[0].decode(encoding='UTF-8')
if inactive in bt_service:
active_counter = counter - 1
else:
active_counter = counter
# If all three bluetooth-related services are active, thenset the status to an up arrow.
if active_counter == counter:
bt_status = "↑" # up arrow
else:
bt_status = "↓" # down arrow
#Check if tje bt_status has changed, or if its the samw
if old_bt_status != bt_status:
old_bt_status = bt_status
bt_status_change_flag = True
else:
bt_status_change_flag = False
return (bt_status, bt_status_change_flag)
def get_lan_service_status(ssid,ssid_change_flag):
global old_lan_status
global not_connected
lan_service = 'ser2net'
inactive = 'inactive'
lan_service = subprocess.Popen(['systemctl', 'is-active', lan_service], stdout=subprocess.PIPE).communicate()[0].decode(encoding='UTF-8')
if inactive in lan_service:
#If there is no ip address, then turn off the ser2net service:
if ssid != not_connected and ssid_change_flag is True:
os.system("systemctl start ser2net") #start the ser2net service.
lan_status = "↑" # up arrow
elif ssid_change_flag is False:
lan_status = "↓" # down arrow
else:
lan_status = "↓" # down arrow
else:
#If there is no ip address, then turn off the ser2net service:
if ssid == not_connected and ssid_change_flag is True:
os.system("systemctl stop ser2net") #start the ser2net service.
lan_status = "↓" # down arrow
elif ssid_change_flag is False:
lan_status = "↑" # up arrow
else:
lan_status = "↑" # up arrow
if old_lan_status != lan_status:
old_lan_status = lan_status
lan_status_change_flag = True
else:
lan_status_change_flag = False
return (lan_status, lan_status_change_flag)
def get_ssid():
global old_ssid
global not_connected
try:
ssid = subprocess.check_output("iwgetid -r", shell = True).decode(encoding='UTF-8')
ssid = ssid.strip()
except subprocess.CalledProcessError:
# grep did not match any lines
ssid = not_connected
if ssid == "":
ssid = not_connected
if old_ssid != ssid:
old_ssid = ssid
ssid_change_flag = True
else:
ssid_change_flag = False
return (ssid, ssid_change_flag)
def get_ip():
global old_host_ip
try:
iface = netifaces.gateways()['default'][netifaces.AF_INET][1]
except Exception:
iface = "N/A"
if iface != "N/A":
host_ip = netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr']
else:
host_ip = "Not Connected"
if old_host_ip != host_ip:
old_host_ip = host_ip
host_ip_change_flag = True
else:
host_ip_change_flag = False
return (host_ip, host_ip_change_flag)
def cap_usb_serial_port():
#Capturess the existing wired serial port in use.
n = 0
usb_serial_port = usb_ser_label + ':'
usb_serial_status_pos = 237
if os.path.exists(dev_dir + usb_ser_port + str(n)):
for i in range(0, 3, 1):
if os.path.exists(dev_dir + usb_ser_port + str(i)):
n += 1
usb_serial_connect = True
usb_serial_status = str(n)
else:
usb_serial_connect = False
usb_serial_status = str(n)
return [usb_serial_port, usb_serial_status_pos, usb_serial_connect, usb_serial_status]
def cap_acm_serial_port():
#Capturess the existing wired serial port in use.
n = 0
acm_serial_port = acm_ser_label + ':'
acm_serial_status_pos = 237
if os.path.exists(dev_dir + acm_ser_port + str(n)):
for i in range(0, 3, 1):
if os.path.exists(dev_dir + acm_ser_port + str(i)):
n += 1
acm_serial_connect = True
acm_serial_status = str(n)
else:
acm_serial_connect = False
acm_serial_status = str(n)
return [acm_serial_port, acm_serial_status_pos, acm_serial_connect, acm_serial_status]
def cap_bt_serial_port():
# Grabs existing bluetooth serial ports:
bt_serial_status_pos = 97
bt_serial_port = bt_ser_label + ':'
if os.path.exists(dev_dir + bt_ser_port):
bt_serial_connect = True
bt_serial_status = "1"
else:
bt_serial_connect = False
bt_serial_status = "0"
return [bt_serial_port, bt_serial_status_pos, bt_serial_connect, bt_serial_status]
def epaper_exit():
epd2in13_V2.epdconfig.module_init()
epd2in13_V2.epdconfig.module_exit()
##############################################################################################################
#End of Function defenition:
#Begin Program
if sys.version_info[0] < 3:
raise Exception("Must be using Python 3")
# Register a handler (function) for the SIGTERM signal
signal.signal(signal.SIGTERM, handler)
try:
#Define frame size for e-ink display
image = Image.new('1', (epd.height, epd.width), int(background)) # clear frame
draw = ImageDraw.Draw(image)
#reset the screen, and clear background
epd.init(epd.FULL_UPDATE)
epd.Clear(background)
#define battery:
# bat_00 = Image.open(os.path.join(picdir, 'battery.png'))
# bat_10 = Image.open(os.path.join(picdir, 'battery-10.png'))
# bat_90 = Image.open(os.path.join(picdir, 'battery-90.png'))
#Draw the non variablers to the to the screen
draw.text((0, 0), host_name, font = f_top_line_font16, fill = int(foreground))
draw.text((50, 0), 'Bat:', font = f_top_line_font16, fill = int(foreground))
draw.line([(0, 17), (250, 17)], fill = int(foreground), width = 2)
draw.text((0, 20), 'Load:', font = f_title_font18, fill = int(foreground))
draw.text((50, 20), 'CPU', font = f_var_font18, fill = int(foreground))
draw.text((153, 20), 'Mem', font = f_var_font18, fill = int(foreground))
draw.text((0, 40), 'SSID:', font = f_title_font18, fill = int(foreground))
draw.text((0, 60), 'IP:', font = f_title_font18, fill = int(foreground))
draw.text((0, 80), 'Svcs:', font = f_title_font18, fill = int(foreground))
draw.text((50, 80), 'BT', font = f_var_font18, fill = int(foreground))
draw.text((153, 80), 'ser2net', font = f_var_font18, fill = int(foreground))
draw.text((0, 100), 'TTY:', font = f_title_font18, fill = int(foreground))
epd.displayPartBaseImage(epd.getbuffer(image.rotate(screen_rotate))) #This is the command to actually place the above to the e-ink display.
epd.sleep()
while True:
try:
draw.rectangle((82, 0, 120, 16), fill = int(background))
# if int(bat_lvl()) <= 10:
# image.paste(bat_00, (82,2))
# else:
draw.text((82, 0), bat_lvl(), font=f_top_line_font16, fill = int(foreground))
draw.rectangle((137, 0, 250, 16), fill = int(background))
draw.text((137, 0), time.strftime('%D %H:%M'), font=f_top_line_font16, fill = int(foreground))
draw.rectangle((89, 19, 152, 39), fill = int(background))
draw.text((89, 20), str(psutil.cpu_percent())+'%', font=f_var_font18, fill = int(foreground))
draw.rectangle((200, 19, 250, 39), fill = int(background))
draw.text((200, 20), str(psutil.virtual_memory().percent)+'%', font=f_var_font18, fill = int(foreground))
#Collect connected ssid, system ip address, bt and lan service status:
ssid, ssid_change_flag = get_ssid()
if ssid_change_flag is True:
ip_host, ip_host_change_flag = get_ip()
lan_service, get_lan_service_change_flag = get_lan_service_status(ssid, ssid_change_flag)
draw.rectangle((50, 39, 198, 59), fill = int(background))
draw.text((50, 40), ssid, font=f_var_font18, fill = int(foreground))
draw.rectangle((50, 59, 198, 79), fill = int(background))
draw.text((50, 60), ip_host, font=f_var_font18, fill = int(foreground))
if get_lan_service_change_flag is True:
draw.rectangle((215, 79, 225, 99), fill = int(background))
draw.text((215, 80), lan_service, font=f_var_spc_char_font18, fill = int(foreground))
# display rfcomm, bluetooth, hci, status.
bt_service, bt_service_change_flag = get_bt_service_status()
if bt_service_change_flag is True:
draw.rectangle((72, 79, 84, 99), fill = int(background))
draw.text((72, 80), bt_service, font=f_var_spc_char_font18, fill = int(foreground))
# Setting up the dynamic parts of tty status
usb_serial_port, usb_serial_status_pos, usb_serial_connect, usb_serial_status = cap_usb_serial_port()
acm_serial_port, acm_serial_status_pos, acm_serial_connect, acm_serial_status = cap_acm_serial_port()
bt_serial_port, bt_serial_status_pos, bt_serial_connect, bt_serial_status = cap_bt_serial_port()
total_serial_lines = int(usb_serial_status) + int(acm_serial_status)
# first, if nothing is connected, then just say that:
#If there are no tty connections, then display full_tty_status variable (saying nothing is attached).
if bt_serial_connect is False and usb_serial_connect is False and acm_serial_connect is False:
full_tty_status = "No tty Connections"
if old_full_tty_status != full_tty_status:
old_full_tty_status = full_tty_status
draw.rectangle((50, 99, 245, 122), fill = int(background))
draw.text((50, 100), full_tty_status, font=f_var_font18, fill = int(foreground))
old_total_serial_lines = 'XX'
else: #Otherwise, display the inidividual state of the ttys.
full_tty_status = ""
old_full_tty_status = full_tty_status
draw.rectangle((50, 99, 152, 122), fill = int(background))
draw.text((50, 100), bt_ser_short_label + ' In:', font=f_var_font18, fill = int(foreground))
draw.text((bt_serial_status_pos, 100), bt_serial_status, font=f_var_font18, fill = int(foreground))
if old_total_serial_lines != total_serial_lines:
draw.rectangle((153, 99, 245, 122), fill = int(background))
draw.text((153, 100), 'Serial Out:', font=f_var_font18, fill = int(foreground))
draw.text((usb_serial_status_pos, 100),str(total_serial_lines), font=f_var_font18, fill = int(foreground))
old_total_serial_lines = total_serial_lines
epd.init(epd.PART_UPDATE)
epd.displayPartial(epd.getbuffer(image.rotate(screen_rotate))) #update the screeen to actually print the above to the e-ink display.
except IOError as e:
syslog.syslog(syslog.LOG_INFO, 'traceback.format_exc():\n%s',traceback.format_exc())
syslog.syslog(syslog.LOG_INFO, 'Shutting Down ser2bt_status - traceback.format_exc():\n%s' ,traceback.format_exc())
epaper_exit()
exit()
#sleep, then resume.
epd.sleep()
time.sleep(end_of_loop_pause)
epd.init(epd.FULL_UPDATE) #Initialize the partial screen
# End of while true loop...
epd.sleep()
# epaper_exit()
exit()
except KeyboardInterrupt:
set_shutdown_flag ('e')
syslog.syslog(syslog.LOG_INFO, 'Quit (SIGINT) Due to Keyboard interrupt when not being run as a service')
epd.init(epd.FULL_UPDATE)
syslog.syslog(syslog.LOG_INFO, 'Shutting Down ser2bt_status - interupted by Control C')
epd.sleep()
exit()
except SystemExit:
syslog.syslog(syslog.LOG_INFO, 'Quit (SIGTERM) from service telling us to terminate')
epd.init(epd.FULL_UPDATE)
syslog.syslog(syslog.LOG_INFO, 'Shutting Down/Restarting service - interupted by service stop, from command, shutdown, or reboot')
epd.sleep()
exit()
except IOError as e:
syslog.syslog(syslog.LOG_ERR, 'Shutting Down ser2bt_status - traceback.format_exc():\n%s' ,traceback.format_exc())
epaper_exit()
exit()