Phone Dial action
The Problem
Do you have not only email and web addresses in your MoinMoin Wiki, but also telephone numbers ?
Ever wanted to just click on them and the number being dialled automagically by your dialling device (which can be an Eurit series ISDN telephone, a modem or another Hayes-compatible device).
The Solution
- attach the device to the com port (I personally use an Ascom Eurit40 ISDN telephone and the Ascom dialer interface for it)
put PhoneDial.py into your action directory
follow the directions at top of PhoneDial.py and change some of your MoinMoin config files
Then click on some tag like FON:01234567 (looks like this: FON:01234567 ) and see your phone dialling
The Warning
This is my first piece of Python and MoinMoin code, so review is definitely needed.
For example, there is a known bug that it loads the FrontPage after you click on a FON link.
I think this can be easiliy fixed by some more experienced MoinMoin action programmer, so please help.
The Code
See: ActionMarket
New in 20020206: you can have characters like "-" and "/" in your phone numbers. They will be removed before the string gets sent to the phone.
1 """
2 MoinMoin - "PhoneDial" action
3 =============================
4
5 Copyright (c) 2002 by Thomas Waldmann <tw@waldmann-edv.de>
6 All rights reserved, see COPYING for details.
7
8 This is released under the Gnu General Public Licence. A copy of
9 this can be found at http://www.opensource.org/licenses/gpl-license.html
10
11 SerialLink class taken from PyGarmin (GPL), see http://pygarmin.sourceforge.net/
12
13 So what is this thing doing and how it has to be configured ?
14 =============================================================
15
16 This action dials a phone number using an Eurit 40 ISDN telephone
17 attached via a serial interface to the SERVERs COM ports.
18
19 You maybe could also use a modem for dialing and then take the call
20 with a phone attached to the same line. This action simply sends an
21 ATD<phonenumber> to the device attached to the serial port.
22
23 Add this to your moin_config.py:
24 phonedial_serialdevice = "COM1" (Win32 and untested)
25 phonedial_serialdevice = "/dev/ttyS0" (Linux)
26
27 Add this to your ./data/intermap.txt (in your wiki):
28 FON http://whatever/moin.cgi?action=PhoneDial&number=
29
30 Add this to your pages (example):
31 Ring my best friend: FON:0123456789
32
33 After saving the page, the FON entry should get a link to the
34 PhoneDial action. And if you click on it, it should dial the number
35 using the device attached to the com port.
36
37 BTW: these are my first footsteps in Python and MoinMoin Programming.
38
39 So if you are more experienced concerning Python (and moinmoin), then
40 please review this and please, if you improve it, send me a copy of your
41 improvements. Thanks.
42
43 Version History:
44
45 20020110 first public version - "it works for me"
46 20020206 filtering out special characters like "-" or "/" for not
47 confusing the Eurit phone
48
49 Known Bugs:
50
51 After clicking on a FON link, you will see the FrontPage.
52
53 Known Limitations:
54
55 It is the web server computer (where moin.cgi runs) that is dialling via
56 the com port. If you work at a different PC far away from the server or
57 if you have multiple phones you want to get dialling, you maybe need more
58 than this script.
59
60 """
61
62 # is this all needed ?:
63 import os, string, time, sys
64 from MoinMoin import config, util, wikiutil, webapi
65 from MoinMoin.Page import Page
66
67 # Now some practical implementations
68
69 class SerialLink:
70 """
71 A serial link will look something like this, though real
72 implementations will probably override most of it.
73 """
74 def __init__(self, f, timeout = 5):
75 self.f = f
76 self.initserial()
77 self.settimeout(timeout)
78
79 def initserial(self):
80 "Set up baud rate, handshaking, etc"
81 pass
82
83 def read(self, n):
84 """
85 Read n bytes and return them. Real implementations should
86 raise a LinkException if there is a timeout > self.timeout
87 """
88 return self.f.read(n)
89
90 def write(self, data):
91 self.f.write(data)
92
93 def settimeout(self, secs):
94 self.timeout = secs
95
96 def __del__(self):
97 """Should close down any opened resources"""
98 pass
99
100
101 class UnixSerialLink(SerialLink):
102
103 def __init__(self, device):
104 f = open(device, "w+", 0)
105 SerialLink.__init__(self, f)
106
107 def initserial(self):
108 from tty import *
109
110 fd = self.f.fileno()
111 setraw(fd)
112 mode = tcgetattr(fd)
113 mode[ISPEED] = mode[OSPEED] = B2400
114 # mode[LFLAG] = mode[LFLAG] | ECHO
115 tcsetattr(fd, TCSAFLUSH, mode)
116
117 def read(self, n):
118 import select
119
120 i = 0
121 data = []
122 while i < n:
123 iset,oset,eset = select.select([self.f.fileno()], [], [], self.timeout)
124 if iset == []:
125 raise LinkException, "time out"
126 b = self.f.read(1)
127 data.append(b)
128 i = i + 1
129 return string.join(data,'')
130
131 def __del__(self):
132 self.f.close()
133
134 # Win32 Serial Link ==================================================
135
136 if os.name == 'nt':
137 from win32file import *
138 import win32con
139
140 class Win32SerialLink(SerialLink):
141 def __init__(self, device):
142 self.device = device
143 handle = CreateFile(device,
144 win32con.GENERIC_READ | win32con.GENERIC_WRITE,
145 0, # exclusive access
146 None, # no security
147 win32con.OPEN_EXISTING,
148 0,
149 None)
150 SerialLink.__init__(self, handle)
151
152 def initserial(self):
153 # Remove anything that was there
154 PurgeComm(self.f, PURGE_TXABORT | PURGE_RXABORT
155 | PURGE_TXCLEAR | PURGE_RXCLEAR )
156
157 # Setup the connection info.
158 dcb = GetCommState( self.f )
159 dcb.BaudRate = CBR_2400
160 dcb.ByteSize = 8
161 dcb.Parity = NOPARITY
162 dcb.StopBits = ONESTOPBIT
163 SetCommState(self.f, dcb)
164
165 def read(self, n):
166 buffer = AllocateReadBuffer(n)
167 rc, data = ReadFile(self.f, buffer)
168 if len(data) != n:
169 raise LinkException, "time out";
170 return data
171
172 def write(self, n):
173 rc,n = WriteFile(self.f, n)
174 if rc:
175 raise LinkException, "WriteFile error";
176
177 def settimeout(self, secs):
178 SerialLink.settimeout(self, secs)
179 # Setup time-outs
180 timeouts = 0xFFFFFFFF, 0, 1000*secs, 0, 1000*secs
181 SetCommTimeouts(self.f, timeouts)
182
183 def __del__(self):
184 CloseHandle(self.f)
185
186
187 class Eurit:
188 """
189 A representation of the Eurit telephone, which is connected
190 via some physical connection, typically a SerialLink of some sort.
191 """
192 def __init__(self):
193 if os.name == 'nt':
194 serialDevice = config.phonedial_serialdevice
195 self.link = Win32SerialLink(serialDevice)
196 else:
197 serialDevice = config.phonedial_serialdevice
198 self.link = UnixSerialLink(serialDevice)
199
200 # === this is the important part, here we do the dialling:
201 def dial(self, number):
202 self.link.write("ATD" + number + "\r");
203 # ========================================================
204
205
206 def execute(pagename, form):
207
208 # get the phone number
209 if form.has_key('number'):
210 number = form['number'].value
211 else:
212 number = ""
213
214 number = string.replace(number,'/','')
215 number = string.replace(number,'-','')
216
217 eurit = Eurit()
218 eurit.dial(number)
219 page = Page(pagename)
220 page.send_page(form, msg="<b>Dialled " + number + ".</b>")
Support area
If you have questions, problems, bug reports, wishes, comments - put them here:
- ...