Als eingefleischter Asterisk-User hat es mich regelmäßig gestört, bei eingehenden Anrufen nicht immer zu wissen, wer mich erreichen will. Während man es sich auf dem Sofa bequem gemacht hat, möchte man schließlich nicht für jeden aufstehen.
Stattdessen wäre es doch schön, direkt zu erfahren, wer der Anrufer ist. Um dies zu realisieren hielt ich eine kontrastreiche, grüne OSD-Einblendung, wie man sie von diversen Tools kennt, für geeignet.
Gesucht war also ein Tool, das einfache Textnachrichten empfängt und als OSD-Einblendung auf dem Bildschirm anzeigt. Leider war ein solches Tool auch nach längerer Recherche nicht zu finden. Stattdessen bin ich auf die folgende Seite gestoßen:
http://www.espend.de/artikel/windows-osd-nachrichtenfenster-vbnet.html
Dort wird eine DLL-Datei beschrieben, die zumindest die Funktion der OSD-Einblendungen abbilden kann. Auf Basis dieser DLL-Datei habe ich ein Visual Basic Programm erstellt, das die Anforderungen erfüllt. Hier der relevante Quellcode:
Imports MrSmarty.CodeProject
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading
Imports System.Media
Public Class Form1
' Set the TcpListener on port 13000.
Dim port As Int32 = 13000
Dim server As New TcpListener(IPAddress.Any, port)
'Dim server As New UdpClient(port)
' Buffer for reading data
Dim bytes(1024) As [Byte]
Dim data As [String] = Nothing
Dim nWorkingWidth As Integer = Screen.PrimaryScreen.WorkingArea.Width
Dim nWorkingHeight As Integer = Screen.PrimaryScreen.WorkingArea.Height
'Top-left corner of text in screen coordinates
'Text at 50% of screenwith and at 80% from the top
Dim pt As Point = New Point((nWorkingWidth / 100) * 5, (nWorkingHeight / 100) * 10)
'Transparency of text
Dim alpha As Integer = 230
'Color of text
Dim textColor As Color = Color.LimeGreen
'Font of text
Dim textFont As New Font("Verdana", 35.0F, FontStyle.Bold)
'How long text will be remain on screen, in millisecond
Dim showTimeMSec As Integer = 7000
'Effect to be applied. Work only if "time" greater than 0
Dim mode As FloatingWindow.AnimateMode = FloatingWindow.AnimateMode.Blend
'Time, in milliseconds, for effect playing. If this equal to 0 "mode" ignored and text showed at once
Dim time As Integer = 370
Dim osd1 As New FloatingOSDWindow
Private Sub listenosd()
' Start listening for client requests.
server.Start()
While True
Dim client As TcpClient = server.AcceptTcpClient()
data = Nothing
' Get a stream object for reading and writing
Dim stream As NetworkStream = client.GetStream()
Dim i As Int32
' Loop to receive all the data sent by the client.
i = stream.Read(bytes, 0, bytes.Length)
While (i <> 0)
' Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i)
' Process the data sent by the client.
'data = data.ToUpper()
Dim msg As [Byte]() = System.Text.Encoding.ASCII.GetBytes(data)
' Send back a response.
'stream.Write(msg, 0, msg.Length)
'Console.WriteLine([String].Format("Sent: {0}", data))
i = stream.Read(bytes, 0, bytes.Length)
End While
' Shutdown and end connection
client.Close()
'Remove Linebreaks
data = Replace(data, vbLf, "")
'Sound abspielen
System.Media.SystemSounds.Asterisk.Play()
'OSD-Nachricht anzeigen
ShowOSDText("<<" + data + ">>")
'Warten
Thread.Sleep(3000)
'Nachricht ausblenden
osd1.HideAnimate(FloatingWindow.AnimateMode.Blend, 20000)
End While
End Sub
Private Sub ShowOSDText(ByVal inputtext As String)
osd1.Show(pt, alpha, textColor, textFont, showTimeMSec, mode, time, inputtext)
End Sub
Private Sub BeendenToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BeendenToolStripMenuItem.Click
NotifyIcon1.Dispose()
Me.Close()
End
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim Thread2 As New Threading.Thread(AddressOf listenosd)
Thread2.Start()
End Sub
End Class
Das Programm empfängt Textnachrichten auf TCP Port 13000 und stellt sie auf dem Bildschirm dar. Auf Seite des Asterisk-Servers habe ich ein kleines Python-Script implementiert, das die Textnachrichten sendet. Die zuständige Funktion sieht so aus:
import socket
.
.
.
def osdmessage(text):
clients=['pc','htpc']
TCP_PORT = 13000
for CLIENT in clients:
try:
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((CLIENT, TCP_PORT))
s.send(text)
s.close()
except:
print('Could not connect to Client '+CLIENT)
Die übrige Implementierung hängt stark von der jeweiligen Asterisk-Installation und deren AGI-Scripts ab.