164918a1cf01d18c9e1c6fc68c6ad3102017936b
Stefan Schuermans quick & dirty phone (EBIP)...

Stefan Schuermans authored 5 years ago

1) #! /usr/bin/env python3
2) """phonesim - phone simulator for EBIP protocol
3) Copyright 2019 Stefan Schuermans <stefan@schuermans.info>
4) Copyleft: CC-BY-SA http://creativecommons.org/licenses/by-sa/3.0/"""
5) 
6) import argparse
7) import gi
8) import os
9) import socket
10) import string
11) import sys
12) import time
13) 
14) gi.require_version('Gtk', '3.0')
Stefan Schuermans avoid deprecated GObject fu...

Stefan Schuermans authored 5 years ago

15) from gi.repository import GLib
Stefan Schuermans quick & dirty phone (EBIP)...

Stefan Schuermans authored 5 years ago

16) from gi.repository import Gtk
17) from gi.repository import Pango
18) 
19) scriptdir = os.path.dirname(os.path.abspath(__file__))
20) 
21) 
22) class Master(object):
23)     """master window of phone simulator"""
24) 
25)     class Client(object):
26)         """EBIP client"""
27) 
28)         def __init__(self, master, addr):
29)             """initialize new client"""
30)             super().__init__()
31)             self.master = master
32)             self.addr = addr
33)             # initialize state
34)             self.last_heartbeat_time = None
35)             self.last_register_time = None
36) 
37)         def heartbeat(self):
38)             """client sent heartbeat"""
39)             now = time.time()
40)             self.last_heartbeat_time = now
41) 
42)         def register(self):
43)             """client registered"""
44)             now = time.time()
45)             self.last_register_time = now
46)             self.last_heartbeat_time = now
47)             self.master.output("client \"{:s}:{:d}\" registered".format(
48)                 self.addr[0], self.addr[1]))
49) 
50)         def tick100ms(self, now):
51)             """periodic 100ms tick"""
52)             # expire client if no heartbeat is received
53)             if now >= self.last_heartbeat_time + 60:
54)                 self.master.output("client \"{:s}:{:d}\" expired".format(
55)                     self.addr[0], self.addr[1]))
56)                 # expire client
57)                 return False
58)             # keep client
59)             return True
60) 
61)     def __init__(self, bind, verbose):
62)         """construct the master window"""
63)         super().__init__()
64)         self.bind = bind
65)         self.verbose = verbose
66)         # state information
67)         now = time.time()
68)         self.clients = {}  # dict: addr -> Client
69)         self.calls = {}  # dict: line number -> Call
70)         self.max_line_no = 2
71)         self.last_line_state = now
72)         # build window
73)         self.builder = Gtk.Builder()
74)         self.builder.add_from_file(scriptdir + "/master.glade")
75)         self.widPhoneNoEntry = self.builder.get_object("PhoneNoEntry")
76)         self.widClientsTextView = self.builder.get_object("ClientsTextView")
77)         handlers = {
78)             "onCall": self.onCall,
79)             "onDestroy": self.onDestroy,
80)         }
81)         self.builder.connect_signals(handlers)
82)         # set up socket
83)         self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
84)         self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
85)         self.sock.bind(self.bind)
Stefan Schuermans avoid deprecated GObject fu...

Stefan Schuermans authored 5 years ago

86)         self.sockInEvId = GLib.io_add_watch(self.sock.makefile(),
87)                                             GLib.IO_IN, self.onRecv)
Stefan Schuermans quick & dirty phone (EBIP)...

Stefan Schuermans authored 5 years ago

88)         # start background actions
Stefan Schuermans avoid deprecated GObject fu...

Stefan Schuermans authored 5 years ago

89)         GLib.timeout_add(100, self.onTimer100ms)
Stefan Schuermans quick & dirty phone (EBIP)...

Stefan Schuermans authored 5 years ago

90)         self.output(
91)             "started (bind=\"{:s}:{:d}\")".format(self.bind[0], self.bind[1]))
92) 
93)     def __del__(self):
94)         """cleanup"""
Stefan Schuermans avoid deprecated GObject fu...

Stefan Schuermans authored 5 years ago

95)         GLib.source_remove(self.sockInEvId)