Den CUCM 6 mit AXL anzapfen

...

Stichwort Array :)

...

Gruß,
Marcus
 
da hatte ich ausch schon was gelesen..in der richtung..ansich gibt der cucm einen xml-string zurück..welchen man dann in ein array laden tut..mit einer php-klasse?
 
Hallo Ihr,

ich habe jetzt nochmal Einiges probiert um an Realtime-Informationen heran zu kommen.

Leider scheitere ich immernoch an ein und dem selben Fehler.

Mein Request:
Code:
POST /axl/ HTTP/1.0
Host:192.168.100.38:8443
Authorization: Basic abCDefgHiJkLmnOpqrst
Accept: text/*
Content-type: text/xml
SOAPAction: "http://schemas.cisco.com/ast/soap/action/#RisPort#SelectCmDevice"
Content-length: 1124

<soapenv:Envelope 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
			xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
			xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
			xmlns:soap="http://schemas.cisco.com/ast/soap/" 
			xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
	<soapenv:Header>
		<AstHeader xsi:type="soap:AstHeader">
			<SessionId xsi:type="xsd:string"/>
		</AstHeader>
	</soapenv:Header>
	<soapenv:Body>
		<soap:SelectCmDevice soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
			<CmSelectionCriteria xsi:type="soap:CmSelectionCriteria">
				<MaxReturnedDevices xsi:type="xsd:unsignedInt">200</MaxReturnedDevices>
				<Class xsi:type="xsd:string">Any</Class>
				<Model xsi:type="xsd:unsignedInt">255</Model>
				<Status xsi:type="xsd:string">Any</Status>
				<SelectBy xsi:type="xsd:string">Name</SelectBy>
				<SelectItems soapenc:arrayType="soap:SelectItem[1]" xsi:type="soapenc:Array">
					<item xsi:type="soap:SelectItem">
						<Item xsi:type="xsd:string">SEP00123456789A</Item>
					</item>
				</SelectItems>
			</CmSelectionCriteria>
		</soap:SelectCmDevice>
	</soapenv:Body>
</soapenv:Envelope>

und die Antwort (der Fehler):

Code:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONIDSSO=DE668BC04C25C984103B0EFFF0F639BA; Path=/
Set-Cookie: JSESSIONID=39BFF0D5F7E4B416939E050CC7D23152; Path=/axl; Secure
SOAPAction: ""
Content-Type: text/xml;charset=utf-8
Content-Length: 552
Date: Wed, 27 Aug 2008 11:16:21 GMT
Connection: close

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Header/>
	<SOAP-ENV:Body>
		<SOAP-ENV:Fault>
			<faultcode>SOAP-ENV:Client</faultcode>
			<faultstring>No Handler found for SelectCmDevice</faultstring>
			<detail>
				<axl:Error xmlns:axl="http://www.cisco.com/AXL/API/1.0">
					<axl:code>5003</axl:code>
					<axl:message>No Handler found for SelectCmDevice</axl:message>
					<request>SelectCmDevice</request>
				</axl:Error>
			</detail>
		</SOAP-ENV:Fault>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Das Abfragen von Informationen mit AXL funktioniert jedoch einwandfrei (z. B. executeSQLQuery, getUser, getPhone, doDeviceReset).

Habt Ihr eine Idee wie man dieses Problem beheben könnte?
Habt Ihr schon mal auf einem anderen Weg die aktuelle IP eines Telefons herausbekommen?


Gruß Franz
 
Hallo Franz..

Soweit ich das sehe, darfst du deinen POST nicht an /axl/ senden.
Eher an etwas wie:

/realtimeservice/services/RisPort?wsdl

Ich bin mir allerdings nicht ganz sicher, ob das der richtige Pfad ist. Im Progamming Guide stehen noch ein paar.

"Cisco Unified Communications Manager Developers Guide 6_0" So oder so ähnlich müsste das heißen, wo es drin steht.

Ich habe allerdings noch ein haufen Fehler, weil die Daten aus mein gesendeten POST falsch sind.
Bist du vielleicht inzwischen weiter?!

Gruß

Rhox
 
Endlich Realtime Informationen

Hallo Rhox,

Dein Tipp war der Schlüssel zum Erfolg. :)
Ich musste also nur meinen Header anpassen und User/PW vom CUCM benutzen.

Jetzt bekomme ich endlich die Informationen die ich brauche.

Anbei der Request inklusive Header, der letztendlich funktioniert hat:
Code:
POST /realtimeservice/services/RisPort HTTP/1.0
Host: <serverip>:8443
Authorization: Basic <base64 encoded user:pass>
Accept: text/*
Content-type: text/xml
SOAPAction: "http://schemas.cisco.com/ast/soap/action/#RisPort#SelectCmDevice"
Content-length: <length of request>

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.cisco.com/ast/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
	<soapenv:Header>
		<AstHeader xsi:type="soap:AstHeader">
			<SessionId xsi:type="xsd:string" />
		</AstHeader>
	</soapenv:Header>
	<soapenv:Body>
		<soap:SelectCmDevice soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
			<CmSelectionCriteria xsi:type="soap:CmSelectionCriteria">
				<MaxReturnedDevices xsi:type="xsd:unsignedInt">200</MaxReturnedDevices>
				<Class xsi:type="xsd:string">Any</Class>
				<Model xsi:type="xsd:unsignedInt">255</Model>
				<Status xsi:type="xsd:string">Any</Status>
				<SelectBy xsi:type="xsd:string">Name</SelectBy>
				<SelectItems soapenc:arrayType="soap:SelectItem[1]" xsi:type="soapenc:Array">
					<item xsi:type="soap:SelectItem">
						<Item xsi:type="xsd:string"></Item>
					</item>
				</SelectItems>
			</CmSelectionCriteria>
		</soap:SelectCmDevice>
	</soapenv:Body>
</soapenv:Envelope>

Folgende 3 Elemente müssen im Header ersetzt werden:
<serverip> = IP des CUCM (z.B. 192.168.2.2)
<base64 encoded "User:pass"> = User/PW getrennt durch einen Doppelpunkt Base64 codiert (z.B. bei Admin:Admin => QWRtaW46QWRtaW4=)
<length of request> = Anzahl der Zeichen des Requests (z.B. 1109)

Gruß Franz
 
...

Hallo Franz,

Freut mich das, es nun klappt. Könntest du evtl. zusätzlich zum Request noch den verwendeten Code posten.


...

Gruß,
Marcus
 
kompletter Code

Hallo Marcus,

na klaro kann ich den kompletten Code posten.

Der komplette Java-Quellcode:
Code:
import java.io.*;
import java.net.*;
import javax.net.ssl.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class CiscoRealtime {

	public static void main(String[] args) {
		byte[] bArray = null; // buffer for reading response from
		Socket socket = null; // socket to AXL server
		OutputStream out = null; // output stream to server
		InputStream in = null; // input stream from server
		String sRealtimeSOAPRequest = ""; // HTTPS header and SOAP payload
		String sRealtimeRequest = null; // will hold only the SOAP payload

		//CCMAdministrator and password
		String authorization = "Admin" + ":" + "Admin";

		// base64 encoding of the username and password
		authorization = new sun.misc.BASE64Encoder().encode(authorization.getBytes());

		// Cisco Realtime Header
		sRealtimeSOAPRequest  = 	"POST /realtimeservice/services/RisPort HTTP/1.0\r\n" +
							"Host: 192.168.2.2:8443\r\n" +
							"Authorization: Basic " + authorization + "\r\n" +
							"Accept: text/*\r\n" +
							"Content-type: text/xml\r\n" +
							"SOAPAction: \"http://schemas.cisco.com/ast/soap/action/#RisPort#SelectCmDevice\"\r\n" +
							"Content-length: ";
		
		// Cisco Realtime Request (aktuelle IPs)		
		sRealtimeRequest  = 	"<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:soap=\"http://schemas.cisco.com/ast/soap/\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
						"	<soapenv:Header>" + 
						"		<AstHeader xsi:type=\"soap:AstHeader\">" +
						"			<SessionId xsi:type=\"xsd:string\"/>" +
						"		</AstHeader>" +
						"	</soapenv:Header>" +
						"	<soapenv:Body>" +
						"		<soap:SelectCmDevice soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
						"			<CmSelectionCriteria xsi:type=\"soap:CmSelectionCriteria\">" +
						"				<MaxReturnedDevices xsi:type=\"xsd:unsignedInt\">200</MaxReturnedDevices>" +
						"				<Class xsi:type=\"xsd:string\">Any</Class>" +
						"				<Model xsi:type=\"xsd:unsignedInt\">255</Model>" +
						"				<Status xsi:type=\"xsd:string\">Any</Status>" +
						"				<SelectBy xsi:type=\"xsd:string\">Name</SelectBy>" +
						"				<SelectItems soapenc:arrayType=\"soap:SelectItem[1]\" xsi:type=\"soapenc:Array\">" +
						"					<item xsi:type=\"soap:SelectItem\">" +
						"						<Item xsi:type=\"xsd:string\"></Item>" +
						"					</item>" +
						"				</SelectItems>" +
						"			</CmSelectionCriteria>" +
						"		</soap:SelectCmDevice>" +
						"	</soapenv:Body>" +
						"</soapenv:Envelope>";
		
		// finish the HTTPS Header
		sRealtimeSOAPRequest += sRealtimeRequest.length();
		sRealtimeSOAPRequest += "\r\n\r\n";

		// now add the SOAP payload to the HTTPS header, which completes the AXL
		// SOAP request
		sRealtimeSOAPRequest += sRealtimeRequest;

		try {
			CiscoRealtime mycr = new CiscoRealtime();

			// Implement the certificate-related stuffs required for sending request via https
			X509TrustManager xtm = mycr.new MyTrustManager();
			TrustManager[] mytm = { xtm };
			SSLContext ctx = SSLContext.getInstance("SSL");
			ctx.init(null, mytm, null);
			SSLSocketFactory sslFact = (SSLSocketFactory) ctx.getSocketFactory();
			socket = (SSLSocket) sslFact.createSocket("192.168.2.2", Integer.parseInt("8443"));
			in = socket.getInputStream();

			// send the request to the server
			// read the response from the server
			StringBuffer sb = new StringBuffer(2048);
			bArray = new byte[2048];
			int ch = 0;
			int sum = 0;
			out = socket.getOutputStream();
			out.write(sRealtimeSOAPRequest.getBytes());
			while ((ch = in.read(bArray)) != -1) {
				sum += ch;
				sb.append(new String(bArray, 0, ch));
			}
			socket.close();

			// output the response to the standard output
			System.out.println(sb.toString());
		} catch (UnknownHostException e) {
			System.err.println("Error connecting to host: " + e.getMessage());
			return;
		} catch (IOException ioe) {
			System.err.println("Error sending/receiving from server: " + ioe.getMessage());
			// close the socket
		} catch (Exception ea) {
			System.err.println("Unknown exception " + ea.getMessage());
			return;
		}
		finally{
			
			try {
				if (socket != null)
					socket.close();
			} catch (Exception exc) {
				exc.printStackTrace();
				System.err.println("Error closing connection to server: "+ exc.getMessage());
			}
		}
	}

	public class MyTrustManager implements X509TrustManager {
		MyTrustManager() {
			// create/load keystore
		}
	
		public void checkClientTrusted(X509Certificate chain[], String authType) throws CertificateException {
		}
		
		public void checkServerTrusted(X509Certificate chain[], String authType) throws CertificateException {
		}
		
		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}
	}
}

Kannst ja mal schreiben ob es Dir geholfen hat.


Gruß Franz
 
...

Vielen Dank.
Es ging mir weniger um einen akuten/konkreten Anwendungsfall als viel mehr darum "da Thema komplett zu haben". Jetzt sollte ja eigentlich alles was man so braucht um mit dem CM zu "reden" da sein.

Ich werde mal versuchen dein Java auf PHP zu heben.


...

Gruß,
Marcus
 
Hat schon mal jemand versucht...den CUCM mit perl anzusprechen?
 
...

Ich will es mal so ausdrücken. Ich weiß aus verlässlicher Quelle das es zumindest mit dem 4 und wenn ich mich recht entsinne auch mit der 6er funktioniert.


...

Gruß,
Marcus
 
klingt schon mal net schlecht, wenn es mit dem 6er funktioniert :)
 
So..nun kann ich auch sagen...perl klappt und das Prima :)

aber so ne Frage am Rande...Änderung des Passwortes/PIN vom EndUser über AXL....das möglich? Welche Funktion? Datenbankeintrag?
 
...


updateUser -> password und pin sind deine Freunde


<password>password</password>
<pin>12345</pin>


Eine Bitte hätte ich da noch (dann wäre der Perlteil hier auch "erledigt")

Poste doch bitte die Perllösung. :)


...

Gruß,
Marcus
 
Hallo zusammen,
hat jemand von euch schon mal versucht mit vb .Net auf den CM6 zuzugreifen? Habe mit dem wsdl Tool die axlapiservice.vb erstellen können und habe auch die Änderungen gemäß der readme erstellt aber bekomme beim instanziieren der Klasse immer den Fehler
Fehler beim Reflektieren des Typs 'AXLSQL.APIRequest'
Kann mir hier jemand einen Tip geben wie ich an der Stelle weiter komme?

Vielen Dank

Ralph
 
Hallo,
ich habe nun schon ewig nichts mehr mit dieser Sache hier gemacht, aber nun ist es mal wieder aktuell geworden...

Leider habe ich nichts mehr von den alten Skripten und der CUCM ist nun auch ein 7.x geworden.

Könnte mir jemand nochmal ein Beispiel posten, was funktioniert?
Auch, wie ich dann eine Rufnummer zu einem bestimmten DEVICENAME herausbekomme? Hatte damals als letztes mit den SQL Statements rumprobiert, bin aber da nie zu einem Ergebnis gekommen... Vielleicht kann mir da nochmal jemand helfen. Auch wie man den Response auswertet.

Das ganze mit PHP natürlich... Achso und ich würde gerne Xampp und SOAP Nativ benutzen. Er mekert aber über SSL, das es in diesem Build nicht drin wäre. Aber ich habe curl in der PHP.ini aktiviert. Hmmm... da auch noch jemand eine Idee zu?

DANKE DANKE DANKE DANKE DANKE

Gruss
Christian
 
Ein erfreuliches Update... Zugriff auf CUCM 7.x, kein Problem...

Allerdings hab ich keine Ahnung, wie ich folgendes realisieren soll...

Ein Idle Url Service wird aktiviert. Dieser Dienst soll dann herausfinden, welche ERSTE Line auf dem IP Phone liegt. Und mit dieser Nummer soll in einer eigenen MySQL DB nach etwas gesucht werden.

Meine Idee war, das ich per GET die MAC-Adresse vom IP Phone bekomme. Mit dieser suche ich dann per AXL/SOAP in der CUCM Datenbank nach der ersten LINE.

Alles gut und schön, aber wie heissen die Tabellen, oder gibt es einen leichteren Weg?

Welches Interface wird abgefragt? http://ccmip/axl/ oder ein anderes?

Gruss und Danke
Christian
 
Beim 4.1(3) hatte ich mal mit solchen Sachen gespielt:
Code:
select NumPlan.DNOrPattern as DirectoryNumber, Device.Name as DeviceName, Device.Description as
UserDeviceProfileName, Device.LoginUserid as UserId, DeviceNumPlanMap.Display as
DisplayIntCallerID,DeviceNumPlanMap.Label as LineTextLabel,numplan.alertingname as
AlertingName,DeviceNumPlanMap.MaxNumCalls, DeviceNumPlanMap.BusyTrigger,
TypeModel.Name AS PhoneType, DeviceNumPlanMap.E164Mask as ExtPhoneMask, NumPlan.CFADestination as
CallFWDALL, NumPlan.CFNADestination as CallFWDNoAnswer, NumPlan.CFBDestination as CallFWDBusy,
devicepool.Name as DevPoolName
from numplan, devicenumplanmap, devicepool, device ,TypeModel
where DeviceNumPlanMap.fknumplan = numplan.pkid
and DeviceNumPlanMap.fkdevice = device.pkid
and device.fkdevicepool = devicepool.pkid
and TypeModel.Name = 'Cisco 7970'
and numplan.tkPatternUsage = 2
order by numplan.DnOrPattern

Obiges liefert als SQL Query so einige Daten zurueck
 
Oh vielen Dank, das wird mir sicher schon etwas weiterhelfen... Ich habe mir nun zusätzlich auch das Data Dictionary vom 7.0 bei Cisco runtergeladen. Dort sind alle Tabellen und Felder vermerkt. Mal schauen, ob diese noch mit dem 4.1.3 übereinstimmen.

Das hier habe ich einfach mal abgesetzt und schon habe ich das ganze Device bekommen... Ich bin also auf einem guten Weg. Mir fehlen da nur noch die Zusammenhänge der Tabellen zwischen dem Device (Hardwaremäßig) und der Line (Virtuell) auf einem Telefon. Aber erstmal probiere ich dein SQL etwas aus :))

Achja das war noch kurz mein Code:
Code:
SELECT * from device WHERE name = 'SEP000F34D6FBEF'

Danke nochmals
und ich bin immer offen für noch mehr Tips...
Gruss
Christian
 
Code:
numplan.tkPatternUsage = 2

war glaube ich die erste Haupt Leitung ;-) Habe keinen Zugriff mehr zum Call Manager... Da gibt es schoene Schane via SQL um z.B. zu schauen wer alles eine Rufumleitung und wohin der Umleitet(5% bedeuted alle DDI's die mit 5 anfangen):

Code:
select DNOrPattern,CFaDestination,CFBDestination,CFnaDestination from NumPlan where DNOrPattern like '5%' and
CFADestination like '[0-9]%' order by DNOrPattern

oder alle Unity umleitungen:

Code:
select DNOrPattern,CFADestination from NumPlan where (CFAVoicemailEnabled = 1) order by DNOrPattern

oder alle Translation Patterns mit Rufnummer whin Sie umleiten und Namen dazu (5% bedeuted alle DDI's die mit 5 anfangen):

Code:
select DNOrPattern,PrefixDigitsOut,Description from NumPlan where DNOrPattern like '5%.' order by DNOrPattern


oder die Anzeige aller Nebenstellen welche nicht z.B. max 5 Anrufe gesetzt haben:

Code:
SELECT Device.Name, NumPlan.DNOrPattern, DeviceNumPlanMap.Display,
DeviceNumPlanMap.MaxNumCalls, DeviceNumPlanMap.BusyTrigger,
TypeModel.Name AS Expr1, DeviceNumPlanMap.NumPlanIndex
FROM DeviceNumPlanMap INNER JOIN
NumPlan ON DeviceNumPlanMap.fkNumPlan = NumPlan.pkid INNER JOIN
Device ON DeviceNumPlanMap.fkDevice = Device.pkid INNER JOIN
TypeModel ON Device.tkModel = TypeModel.Enum
WHERE (DeviceNumPlanMap.MaxNumCalls = '4') AND (TypeModel.Name = 'Cisco 7970') order by DNOrPattern
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.