### Class Documentation Example Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/STYLEGUIDE_JAVADOC.md Use for documenting classes and interfaces. Includes a one-sentence summary, detailed description, thread-safety notes, and example usage. ```java /** * One-sentence summary describing the class's primary responsibility. * *

Additional context and details about the class behavior, usage patterns, * or important implementation notes. Use paragraph tags for multi-paragraph * descriptions. * *

Thread-safety: Specify if the class is thread-safe or not. * *

Example usage: *

{@code
 * MyClass obj = new MyClass();
 * obj.doSomething();
 * }
* * @see RelatedClass * @since 2.1.5 */ public class MyClass { } ``` -------------------------------- ### Null Handling Documentation Example Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/STYLEGUIDE_JAVADOC.md Clearly document null handling for parameters and return values, including constraints and potential exceptions like NullPointerException. ```java /** * Processes the given device. * * @param device the device to process, must not be {@code null} * @return the processed result, or {@code null} if processing failed * @throws NullPointerException if device is {@code null} */ ``` -------------------------------- ### Method Documentation Example Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/STYLEGUIDE_JAVADOC.md Use for documenting methods. Includes a summary, details on behavior and side effects, and descriptions for parameters, return values, and exceptions. ```java /** * One-sentence summary of what the method does. * *

Additional details about the method's behavior, side effects, * or important considerations. * * @param paramName description of the parameter and its constraints * @param anotherParam description including valid values or ranges * @return description of the return value and what it represents * @throws ExceptionType when and why this exception is thrown * @see #relatedMethod() */ public ReturnType methodName(Type paramName, Type anotherParam) throws ExceptionType { } ``` -------------------------------- ### UPnP Action Invocation Example Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/STYLEGUIDE_JAVADOC.md Demonstrates how to invoke a UPnP action on a service and set argument values. Ensure the action is properly initialized before invocation. ```java Action action = service.getAction("SetVolume"); action.setArgumentValue("DesiredVolume", 50); action.postControlAction(); ``` -------------------------------- ### Field Documentation Example Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/STYLEGUIDE_JAVADOC.md Use for documenting fields, particularly constants. Provides a brief description of what the field represents. ```java /** * Brief description of what this field represents. */ public static final String CONSTANT_NAME = "value"; ``` -------------------------------- ### Implement a UPnP Clock Device Source: https://context7.com/cybergarage/cybergarage-upnp/llms.txt This example demonstrates creating a UPnP clock device by extending the Device class. It loads device and service descriptions from XML strings, registers action and query listeners, and manages state variables. Use this for creating custom UPnP devices. ```java import org.cybergarage.upnp.*; import org.cybergarage.upnp.device.*; import org.cybergarage.upnp.control.*; public class ClockDevice extends Device implements ActionListener, QueryListener { private static final String DEVICE_DESC = "\n" + " " + " 10 " + " " + " urn:schemas-upnp-org:device:clock:1 " + " My Clock " + " Acme Corp " + " Clock " + " uuid:acme-clock-001 " + " " + " " + " urn:schemas-upnp-org:service:timer:1 " + " urn:upnp-org:serviceId:timer:1 " + " /timer/desc.xml " + " /timer/control " + " /timer/eventSub " + " " + " " + " " + ""; private static final String SERVICE_DESC = "\n" + " " + " 10 " + " " + " " + " GetTime " + " " + " CurrentTime" + " Time" + " out " + " " + " " + " " + " " + " " + " Timestring " + " " + " " + ""; private StateVariable timeVar; public ClockDevice() throws InvalidDescriptionException { super(); loadDescription(DEVICE_DESC); // parse inline XML Service timerSvc = getService("urn:schemas-upnp-org:service:timer:1"); timerSvc.loadSCPD(SERVICE_DESC); // load service description getAction("GetTime").setActionListener(this); // per-action listener timerSvc.setQueryListener(this); // state variable query listener timeVar = getStateVariable("Time"); setHTTPPort(4004); // optional: override default setLeaseTime(1800); // SSDP lease time in seconds } // Called when a control point invokes an action @Override public boolean actionControlReceived(Action action) { if ("GetTime".equals(action.getName())) { action.getArgument("CurrentTime").setValue( new java.util.Date().toString()); return true; // return true = success; framework sends 200 OK } action.setStatus(UPnP.INVALID_ACTION, "Unknown action"); return false; // return false = framework sends UPnP error response } // Called when a control point queries a state variable directly @Override public boolean queryControlReceived(StateVariable stateVar) { stateVar.setValue(new java.util.Date().toString()); return true; } // Push an updated time value to all event subscribers public void tick() { timeVar.setValue(new java.util.Date().toString()); // triggers GENA notify automatically } public static void main(String[] args) throws Exception { ClockDevice dev = new ClockDevice(); dev.start(); // begins HTTP server, SSDP announce, Advertiser thread System.out.println("Device running, press Enter to stop"); System.in.read(); dev.stop(); // sends ssdp:byebye and tears down all sockets } } ``` -------------------------------- ### Initiate UPnP Control Point Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Create and start a UPnP control point. The control point automatically multicasts a discovery message upon activation. ```java import org.cybergarage.upnp.*; import org.cybergarage.upnp.device.*; // ...existing code... ControlPoint ctrlPoint = new ControlPoint(); // ...existing code... ctrlPoint.start(); ``` -------------------------------- ### Get Service, Action, and State Variable by Name (Java) Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Demonstrates how to retrieve a specific service, action, and state variable from a device using their respective names. This is useful for direct interaction with device components. ```java Device clockDev = ...; Service timerService = clockDev.getService("timer"); Action getTimeAct = clockDev.getAction("GetTime"); StateVariable timeStat = clockDev.getStateVariable("time"); ``` -------------------------------- ### UPnP Action Class Documentation Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/STYLEGUIDE_JAVADOC.md Javadoc for the Action class, explaining its purpose, thread-safety, and providing an example of its usage. This class represents an invokable UPnP action. ```java /** * Represents a UPnP action that can be invoked on a service. * *

Actions are methods exposed by UPnP services that can be called * remotely by control points. Each action has a name, a list of input * arguments, and a list of output arguments. * *

This class is thread-safe. Multiple threads can safely invoke * the same action instance concurrently. * *

Example usage: *

{@code
 * Action action = service.getAction("SetVolume");
 * action.setArgumentValue("DesiredVolume", 50);
 * action.postControlAction();
 * }
* * @see Service * @see Argument * @since 2.1.5 */ public class Action { /** * Posts this action to the device and waits for the response. * *

This method sends a SOAP request to the device's control URL * and blocks until a response is received or a timeout occurs. * The response arguments can be retrieved after successful execution. * * @return {@code true} if the action was executed successfully, * {@code false} if an error occurred * @throws IllegalStateException if the action is not properly initialized * @see #getStatus() */ public boolean postControlAction() throws IllegalStateException { // implementation } } ``` -------------------------------- ### Listen for SSDP Notify and Search Responses Source: https://context7.com/cybergarage/cybergarage-upnp/llms.txt Implement NotifyListener to inspect raw SSDP NOTIFY packets or SearchResponseListener to inspect M-SEARCH responses for custom discovery logic. This example shows how to add both listeners. ```java import org.cybergarage.upnp.*; import org.cybergarage.upnp.device.*; import org.cybergarage.upnp.ssdp.SSDPPacket; ControlPoint cp = new ControlPoint(); // Raw SSDP NOTIFY listener cp.addNotifyListener(new NotifyListener() { @Override public void deviceNotifyReceived(SSDPPacket packet) { System.out.println("NOTIFY USN=" + packet.getUSN() + " NT=" + packet.getNT() + " NTS=" + packet.getNTS() + " Location=" + packet.getLocation()); } }); // M-SEARCH response listener cp.addSearchResponseListener(new SearchResponseListener() { @Override public void deviceSearchResponseReceived(SSDPPacket packet) { System.out.println("SEARCH-RESP USN=" + packet.getUSN() + " ST=" + packet.getST() + " Location=" + packet.getLocation()); } }); cp.start(); cp.search("upnp:rootdevice"); Thread.sleep(5000); cp.stop(); ``` -------------------------------- ### ControlPoint Device Discovery and Management Source: https://context7.com/cybergarage/cybergarage-upnp/llms.txt Use ControlPoint to manage device discovery via SSDP M-SEARCH and NOTIFY. Add listeners to receive callbacks when devices join or leave the network. Start the ControlPoint to begin discovery and stop it to clean up resources. ```java import org.cybergarage.upnp.*; import org.cybergarage.upnp.device.DeviceChangeListener; ControlPoint cp = new ControlPoint(); // Receive callbacks when devices join or leave the network cp.addDeviceChangeListener(new DeviceChangeListener() { @Override public void deviceAdded(Device dev) { System.out.println("Added: " + dev.getFriendlyName() + " type=" + dev.getDeviceType() + " location=" + dev.getLocation()); } @Override public void deviceRemoved(Device dev) { System.out.println("Removed: " + dev.getFriendlyName()); } }); cp.start(); // opens SSDP/HTTP sockets, sends initial M-SEARCH, starts Disposer thread // Wait for discovery (in a real app use a latch or callback) Thread.sleep(3000); DeviceList devices = cp.getDeviceList(); System.out.println("Found " + devices.size() + " device(s):"); for (int i = 0; i < devices.size(); i++) { Device d = devices.getDevice(i); System.out.printf(" [%d] %s UDN=%s%n", i, d.getFriendlyName(), d.getUDN()); } // Trigger an explicit M-SEARCH for a specific device type cp.search("urn:schemas-upnp-org:device:MediaServer:1"); cp.stop(); ``` -------------------------------- ### Get and Iterate Root Device List Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Retrieve the list of discovered root devices using getDeviceList() and iterate through them to access properties like the friendly name. ```java ControlPoint ctrlPoint = new ControlPoint(); // ...existing code... ctrlPoint.start(); // ...existing code... DeviceList rootDevList = ctrlPoint.getDeviceList(); int nRootDevs = rootDevList.size(); for (int n = 0; n < nRootDevs; n++) { Device dev = rootDevList.getDevice(n); String devName = dev.getFriendlyName(); System.out.println("[" + n + "] = " + devName); } ``` -------------------------------- ### Get Embedded Device by Friendly Name (Java) Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Retrieves an embedded device from a parent device using its friendly name. Ensure the friendly name is unique if multiple devices share it. ```java Device homeServerDev = ...; Device musicDev = homeServerDev.getDevice("music"); ``` -------------------------------- ### Override HTTPRequestListener in ClockDevice Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Example of a ClockDevice subclass overriding httpRequestReceived to serve a presentation page. It checks the URI and returns an HTML response. ```java import org.cybergarage.http.*; // ...existing code... public class ClockDevice extends Device implements ActionListener, QueryListener { // ...existing code... private final static String PRESENTATION_URI = "/presentation"; public void httpRequestReceived(HTTPRequest httpReq) { String uri = httpReq.getURI(); if (!uri.startsWith(PRESENTATION_URI)) { super.httpRequestReceived(httpReq); return; } Clock clock = Clock.getInstance(); String contents = "

" + clock.toString() + "

"; HTTPResponse httpRes = new HTTPResponse(); httpRes.setStatusCode(HTTPStatus.OK); httpRes.setContent(contents); httpReq.post(httpRes); } } ``` -------------------------------- ### Query State Variable Value Source: https://context7.com/cybergarage/cybergarage-upnp/llms.txt Reads the current value of a state variable directly from a UPnP device. Ensure the ControlPoint is started and the device is discovered before querying. ```java import org.cybergarage.upnp.*; ControlPoint cp = new ControlPoint(); cp.start(); Thread.sleep(2000); Device clockDev = cp.getDevice("My Clock"); StateVariable timeVar = clockDev.getStateVariable("Time"); if (timeVar.postQueryControl()) { System.out.println("Time variable value: " + timeVar.getValue()); } else { UPnPStatus err = timeVar.getUPnPStatus(); System.err.println("Query failed: " + err.getCode() + " " + err.getDescription()); } // Inspect allowed value constraints Argument arg = clockDev.getAction("SetTime").getArgument("NewTime"); StateVariable related = arg.getRelatedStateVariable(); if (related != null) { if (related.hasAllowedValueList()) { AllowedValueList list = related.getAllowedValueList(); System.out.println("Allowed values: " + list); } if (related.hasAllowedValueRange()) { AllowedValueRange range = related.getAllowedValueRange(); System.out.println("Range: " + range.getMinimum() + " – " + range.getMaximum() + " step " + range.getStep()); } } cp.stop(); ``` -------------------------------- ### Get Allowed Value Range or List Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Retrieve the allowed value range or list for a state variable associated with an argument. Checks for the existence of these properties before accessing them. ```java Device clockDev = ...; Action timeAct = clockDev.getAction("SetTime"); Argument timeArg = timeAct.getArgument("time"); StateVariable stateVar = timeArg.getRelatedStateVariable(); if (stateVar != null) { if (stateVar.hasAllowedValueRange()) { AllowedValueRange valRange = stateVar.getAllowedValueRange(); // ...existing code... } if (stateVar.hasAllowedValueList()) { AllowedValueList valList = stateVar.getAllowedValueList(); // ...existing code... } } ``` -------------------------------- ### Initiate UPnP Device from Description File Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Initiates a UPnP device using an XML description file. Catches InvalidDescriptionException for invalid descriptions. ```java import org.cybergarage.upnp.*; import org.cybergarage.upnp.device.*; String descriptionFileName = "description/description.xml"; try { Device upnpDev = new Device(descriptionFileName); // ...existing code... upnpDev.start(); } catch (InvalidDescriptionException e) { System.out.println("InvalidDescriptionException = " + e.getMessage()); } ``` -------------------------------- ### Load UPnP Device from File Source: https://context7.com/cybergarage/cybergarage-upnp/llms.txt Loads the root device description from the filesystem. Ensure description XMLs are bundled as classpath resources. The HTTP port and description URI can be optionally configured. ```java import org.cybergarage.upnp.Device; import org.cybergarage.upnp.device.InvalidDescriptionException; try { Device dev = new Device("description/rootdevice.xml"); dev.setHTTPPort(4004); // optional; auto-selected if taken dev.setDescriptionURI("/desc.xml"); // URI served by built-in HTTP server dev.start(); System.out.println("Running: " + dev.getFriendlyName() + " UDN=" + dev.getUDN() + " HTTP port=" + dev.getHTTPPort()); // ... dev.stop(); } catch (InvalidDescriptionException e) { System.err.println("Bad description: " + e.getMessage()); } ``` -------------------------------- ### Initiate UPnP Device from String Descriptions Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Loads UPnP device and service descriptions from XML strings instead of files. Handles InvalidDescriptionException if descriptions are invalid. ```java String DEVICE_DESCRIPTION = "\n" + " " + // ...existing code... ""; String SERVICE_DESCRIPTION = "\n" + " " + // ...existing code... ""; try { Device upnpDev = new Device(); boolean descSuccess = upnpDev.loadDescription(DEVICE_DESCRIPTION); Service upnpService = upnpDev.getService("urn:schemas-upnp-org:service:****:1"); boolean scpdSuccess = upnpService.loadSCPD(SERVICE_DESCRIPTION); } catch (InvalidDescriptionException e) { System.out.println("InvalidDescriptionException = " + e.getMessage()); } ``` -------------------------------- ### Run Security Code Analysis Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/JAVADOC_STATUS.md This placeholder command indicates where to run a security analysis tool like CodeQL. Verify that no security vulnerabilities are introduced by documentation changes. ```bash # Use codeql_checker tool ``` -------------------------------- ### Output Device Actions and State Variables (Java) Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Iterates through all services of a device, printing the names of their actions and state variables. This helps in understanding a device's capabilities. ```java Device dev = ...; ServiceList serviceList = dev.getServiceList(); int serviceCnt = serviceList.size(); for (int n = 0; n < serviceCnt; n++) { Service service = serviceList.getService(n); ActionList actionList = service.getActionList(); int actionCnt = actionList.size(); for (int i = 0; i < actionCnt; i++) { Action action = actionList.getAction(i); System.out.println("action [" + i + "] = " + action.getName()); } ServiceStateTable stateTable = service.getServiceStateTable(); int varCnt = stateTable.size(); for (int i = 0; i < varCnt; i++) { StateVariable stateVar = stateTable.getServiceStateVariable(i); System.out.println("stateVar [" + i + "] = " + stateVar.getName()); } } ``` -------------------------------- ### Implement UPnP Device Control Listeners Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Implement ActionListener and QueryListener interfaces to handle control actions and queries from control points. Set listeners using Device::setActionListener() or Service::setActionListener() for actions, and Device::setQueryListener() or Service::setQueryListener() for queries. ```java public class ClockDevice extends Device implements ActionListener, QueryListener { public ClockDevice() { super("/clock/www/description.xml"); Action setTimeAction = getAction("SetTime"); setTimeAction.setActionListener(this); Action getTimeAction = getAction("GetTime"); getTimeAction.setActionListener(this); StateVariable stateVar = getStateVariable("Timer"); stateVar.setQueryListener(this); } public boolean actionControlReceived(Action action) { ArgumentList argList = action.getArgumentList(); String actionName = action.getName(); if (actionName.equals("SetTime")) { Argument inTime = argList.getArgument("time"); String timeValue = inTime.getValue(); if (timeValue == null || timeValue.length() <= 0) return false; // ...existing code... Argument outResult = argList.getArgument("result"); outResult.setValue("TRUE"); return true; } else if (actionName.equals("GetTime")) { String currTimeStr = ...; Argument currTimeArg = argList.getArgument("currTime"); currTimeArg.setValue(currTimeStr); return true; } action.setStatus(UPnP.INVALID_ACTION, "..."); return false; } public boolean queryControlReceived(StateVariable stateVar) { String varName = stateVar.getName(); if (varName.equals("Time")) { String currTimeStr = ...; stateVar.setValue(currTimeStr); return true; } stateVar.setStatus(UPnP.INVALID_VAR, "..."); return false; } } ``` -------------------------------- ### Open Generated Javadoc API Docs Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/JAVADOC_STATUS.md This command opens the generated Javadoc API documentation in the default web browser. Review the HTML output for readability and correctness. ```bash open target/site/apidocs/index.html ``` -------------------------------- ### Configure UPnP Network Settings Source: https://context7.com/cybergarage/cybergarage-upnp/llms.txt Customize network interface selection, IP version usage, and multicast TTL. These settings must be configured before creating any Device or ControlPoint instances. ```java import org.cybergarage.upnp.UPnP; // Force IPv4 only (default: both IPv4 and IPv6) UPnP.setEnable(UPnP.USE_ONLY_IPV4_ADDR); // Force IPv6 only UPnP.setEnable(UPnP.USE_ONLY_IPV6_ADDR); // Change IPv6 multicast scope (default: link-local) UPnP.setEnable(UPnP.USE_IPV6_SITE_LOCAL_SCOPE); // Include loopback interfaces (useful for unit tests) UPnP.setEnable(UPnP.USE_LOOPBACK_ADDR); // Adjust SSDP multicast TTL (default: 4) UPnP.setTimeToLive(8); // Override the XML parser (must be called before any Device or ControlPoint is created) // UPnP.setXMLParser(new org.cybergarage.xml.parser.JaxpParser()); System.out.println(UPnP.getServerName()); // e.g. "Linux/5.15.0 UPnP/1.0 CyberLinkJava/3.0" ``` -------------------------------- ### Post Action Control Request Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Use this to send an action control message to a device, setting input arguments and processing the response. Ensure all input arguments are set before posting. ```java Device clockDev = ...; Action setTimeAct = clockDev.getAction("SetTime"); String newTime = ...; setTimeAct.setArgumentValue("time", newTime); if (setTimeAct.postControlAction()) { ArgumentList outArgList = setTimeAct.getOutputArgumentList(); int nOutArgs = outArgList.size(); for (int n = 0; n < nOutArgs; n++) { Argument outArg = outArgList.getArgument(n); String name = outArg.getName(); String value = outArg.getValue(); // ...existing code... } } else { UPnPStatus err = setTimeAct.getUPnPStatus(); System.out.println("Error Code = " + err.getCode()); System.out.println("Error Desc = " + err.getDescription()); } ``` -------------------------------- ### Implement UPnP ActionListener and QueryListener Source: https://context7.com/cybergarage/cybergarage-upnp/llms.txt Handles incoming SOAP action calls and direct state-variable queries. Register listeners using Device.setActionListener() or Service.setActionListener(). ```java import org.cybergarage.upnp.*; import org.cybergarage.upnp.control.*; public class LightDevice extends Device implements ActionListener, QueryListener { public LightDevice() throws Exception { super("description/light.xml"); Service svc = getService("urn:schemas-upnp-org:service:SwitchPower:1"); svc.loadSCPD("description/SwitchPower1.xml"); // Register one listener for ALL actions in the device (including sub-devices) setActionListener(this); setQueryListener(this); } @Override public boolean actionControlReceived(Action action) { String name = action.getName(); ArgumentList args = action.getArgumentList(); if ("SetTarget".equals(name)) { String newTarget = args.getArgument("newTargetValue").getValue(); boolean on = "1".equals(newTarget) || "true".equalsIgnoreCase(newTarget); applySwitch(on); return true; } if ("GetTarget".equals(name)) { args.getArgument("RetTargetValue").setValue(isOn() ? "1" : "0"); return true; } if ("GetStatus".equals(name)) { args.getArgument("ResultStatus").setValue(isOn() ? "1" : "0"); return true; } // Unknown action — return a specific UPnP error action.setStatus(401, "Invalid Action"); return false; } @Override public boolean queryControlReceived(StateVariable stateVar) { if ("Status".equals(stateVar.getName())) { stateVar.setValue(isOn() ? "1" : "0"); return true; } stateVar.setStatus(404, "Invalid Var"); return false; } private boolean lightOn = false; private void applySwitch(boolean on) { lightOn = on; } private boolean isOn() { return lightOn; } } ``` -------------------------------- ### Compile Javadoc Documentation Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/JAVADOC_STATUS.md This command compiles the Javadoc documentation for the project using Maven. Ensure this command runs without errors before committing changes. ```bash mvn javadoc:javadoc ``` -------------------------------- ### Add cybergarage-upnp to Maven Project Source: https://context7.com/cybergarage/cybergarage-upnp/llms.txt Include the core artifact for UPnP functionality. The optional 'std' artifact provides standard UPnP device profiles. ```xml org.cybergarage.upnp core 2.1.5 org.cybergarage.upnp std 2.1.5 ``` -------------------------------- ### Print Embedded Device Friendly Names (Java) Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Recursively prints the friendly names of all embedded devices within a given device. This is useful for exploring device hierarchies. ```java public void printDevice(Device dev) { String devName = dev.getFriendlyName(); System.out.println(devName); DeviceList childDevList = dev.getDeviceList(); int nChildDevs = childDevList.size(); for (int n = 0; n < nChildDevs; n++) { Device childDev = childDevList.getDevice(n); printDevice(childDev); } } // ...existing code... Device rootDev = ...; // ...existing code... DeviceList childDevList = rootDev.getDeviceList(); int nChildDevs = childDevList.size(); for (int n = 0; n < nChildDevs; n++) { Device childDev = childDevList.getDevice(n); printDevice(childDev); } ``` -------------------------------- ### Custom HTTP Presentation Page for UPnP Device Source: https://context7.com/cybergarage/cybergarage-upnp/llms.txt Override httpRequestRecieved in a Device subclass to serve custom content at a presentation URL. For unrecognized URIs, always delegate to the superclass. ```java import org.cybergarage.upnp.Device; import org.cybergarage.http.*; public class ClockDeviceWithUI extends Device { private static final String PRESENTATION_URI = "/presentation"; public ClockDeviceWithUI() throws Exception { super("description/clock.xml"); setPresentationURL(PRESENTATION_URI); } @Override public void httpRequestRecieved(HTTPRequest httpReq) { String uri = httpReq.getURI(); if (uri != null && uri.startsWith(PRESENTATION_URI)) { String html = "

Clock: " + new java.util.Date() + "

"; HTTPResponse res = new HTTPResponse(); res.setStatusCode(HTTPStatus.OK); res.setContentType("text/html"); res.setContent(html); httpReq.post(res); } else { super.httpRequestRecieved(httpReq); // let the framework handle descriptions, SOAP, etc. } } } ``` -------------------------------- ### Run Automated Code Review Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/JAVADOC_STATUS.md This placeholder command indicates where to run an automated code review tool. Consult project guidelines for the specific tool and usage. ```bash # Use code_review tool ``` -------------------------------- ### Receive UPnP Search Responses Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Implement the SearchResponseListener interface to receive responses to device search requests. This allows processing of discovered devices. ```java public class MyCtrlPoint extends ControlPoint implements SearchResponseListener { public MyCtrlPoint() { // ...existing code... addSearchResponseListener(this); start(); // ...existing code... search("upnp:rootdevice"); } public void deviceSearchResponseReceived(SSDPPacket ssdpPacket) { String uuid = ssdpPacket.getUSN(); String target = ssdpPacket.getST(); String location = ssdpPacket.getLocation(); // ...existing code... } } ``` -------------------------------- ### Set Device-Wide Action and Query Listeners Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Set a single listener for all actions and queries within a device by calling setActionListener(this) and setQueryListener(this) in the device constructor. This simplifies listener management for devices with many services. ```java class ClockDevice extends Device implements ActionListener, QueryListener { public ClockDevice() { super("/clock/www/description.xml"); setActionListener(this); setQueryListener(this); } public boolean actionControlReceived(Action action) { // ...existing code... } public boolean queryControlReceived(StateVariable stateVar) { // ...existing code... } } ``` -------------------------------- ### Find Root Device by Friendly Name Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Locate a specific root device from the discovered list using its friendly name with the getDevice() method. ```java ControlPoint ctrlPoint = new ControlPoint(); // ...existing code... ctrlPoint.start(); // ...existing code... Device homeServerDev = ctrlPoint.getDevice("xxxx-home-server"); ``` -------------------------------- ### Deprecated API Documentation Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/STYLEGUIDE_JAVADOC.md Document deprecated APIs with a clear explanation of why they are deprecated and what to use instead. Specify the version when it will be removed. ```java /** * Brief description. * * @deprecated Use {@link NewClass#newMethod()} instead. This method * will be removed in version 3.0. */ @Deprecated public void oldMethod() { } ``` -------------------------------- ### Traverse UPnP Device Structure Source: https://context7.com/cybergarage/cybergarage-upnp/llms.txt Recursively introspects a device's structure, including embedded devices, services, actions, and state variables. Uses methods like getDeviceList(), getServiceList(), getActionList(), and getServiceStateTable(). ```java import org.cybergarage.upnp.*; public static void printDevice(Device dev, String indent) { System.out.println(indent + "Device: " + dev.getFriendlyName() + " [" + dev.getDeviceType() + "]"); ServiceList services = dev.getServiceList(); for (int s = 0; s < services.size(); s++) { Service svc = services.getService(s); System.out.println(indent + " Service: " + svc.getServiceType()); ActionList actions = svc.getActionList(); for (int a = 0; a < actions.size(); a++) { Action act = actions.getAction(a); System.out.println(indent + " Action: " + act.getName()); } ServiceStateTable stateTable = svc.getServiceStateTable(); for (int v = 0; v < stateTable.size(); v++) { StateVariable var = stateTable.getServiceStateVariable(v); System.out.println(indent + " StateVar: " + var.getName() + " (sendEvents=" + var.isSendEvents() + ")"); } } DeviceList children = dev.getDeviceList(); for (int d = 0; d < children.size(); d++) { printDevice(children.getDevice(d), indent + " "); } } ``` -------------------------------- ### postControlAction Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/STYLEGUIDE_JAVADOC.md Posts this action to the device and waits for the response. This method sends a SOAP request to the device's control URL and blocks until a response is received or a timeout occurs. ```APIDOC ## postControlAction() ### Description Posts this action to the device and waits for the response. This method sends a SOAP request to the device's control URL and blocks until a response is received or a timeout occurs. The response arguments can be retrieved after successful execution. ### Method Signature `public boolean postControlAction() throws IllegalStateException` ### Returns `true` if the action was executed successfully, `false` if an error occurred. ### Throws - `IllegalStateException` if the action is not properly initialized. ### See Also - #getStatus() ``` -------------------------------- ### ControlPoint Sending Action Control Requests Source: https://context7.com/cybergarage/cybergarage-upnp/llms.txt Use Action.postControlAction() to send SOAP requests to a device and block until a response is received. Set all input argument values before calling this method; output argument values are populated on success. Handle potential errors by checking the UPnPStatus. ```java import org.cybergarage.upnp.*; ControlPoint cp = new ControlPoint(); cp.start(); Thread.sleep(3000); Device clockDev = cp.getDevice("My Clock"); // by friendlyName, UDN, or device type if (clockDev == null) { System.out.println("Clock not found"); cp.stop(); return; } // Invoke the GetTime action Action getTime = clockDev.getAction("GetTime"); if (getTime.postControlAction()) { String currentTime = getTime.getArgumentValue("CurrentTime"); System.out.println("Current time: " + currentTime); } else { UPnPStatus err = getTime.getStatus(); System.err.println("Error " + err.getCode() + ": " + err.getDescription()); } // Invoke SetTime action (has an input argument) Action setTime = clockDev.getAction("SetTime"); setTime.setArgumentValue("NewTime", "12:00:00"); if (setTime.postControlAction()) { System.out.println("SetTime result: " + setTime.getArgumentValue("Result")); } else { UPnPStatus err = setTime.getStatus(); System.err.println("SetTime failed: " + err.getCode() + " " + err.getDescription()); } cp.stop(); ``` -------------------------------- ### Listen for UPnP Device Changes Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Implement the DeviceChangeListener interface to be notified only when devices are added or removed from the UPnP network. This is an alternative to handling all notify events. ```java public class MyCtrlPoint extends ControlPoint implements DeviceChangeListener { public MyCtrlPoint() { // ...existing code... addDeviceChangeListener(this); start(); } public void deviceAdded(Device dev) { // ...existing code... } public void deviceRemoved(Device dev) { // ...existing code... } } ``` -------------------------------- ### Verify Javadoc Warnings Count Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/JAVADOC_STATUS.md This command checks the total number of Javadoc warnings generated by the Maven build. It's useful for tracking overall documentation progress. ```bash mvn -q javadoc:javadoc 2>&1 | grep -c "warning:" ``` -------------------------------- ### Subscribe to Device Events Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Subscribe to events from a specific service on a device. Returns true if the subscription is accepted, allowing retrieval of the subscription ID and timeout. ```java ControlPoint ctrlPoint = ...; Device clockDev = ctrlPoint.getDevice("xxxx-clock"); Service timeService = clockDev.getService("time:1"); boolean subRet = ctrlPoint.subscribe(timeService); if (subRet) { String sid = timeService.getSID(); long timeout = timeService.getTimeout(); } ``` -------------------------------- ### Receive UPnP Notify Events Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Implement the NotifyListener interface to receive device notification events. This allows automatic handling of device additions, removals, and expirations. ```java public class MyCtrlPoint extends ControlPoint implements NotifyListener { public MyCtrlPoint() { // ...existing code... addNotifyListener(this); start(); } public void deviceNotifyReceived(SSDPPacket ssdpPacket) { String uuid = ssdpPacket.getUSN(); String target = ssdpPacket.getNT(); String subType = ssdpPacket.getNTS(); String location = ssdpPacket.getLocation(); // ...existing code... } } ``` -------------------------------- ### Enable IPv6 Only Mode Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Configure the UPnP library to exclusively use IPv6 interfaces. This setting must be applied before creating devices or control points. ```java UPnP.setEnable(UPnP.USE_ONLY_IPV6_ADDR); ``` -------------------------------- ### Implement Event Listener Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Implement the EventListener interface to receive state change notifications from devices. The eventNotifyReceived method should contain the logic for handling incoming events. ```java public class MyControlPoint extends ControlPoint implements EventListener { public MyControlPoint() { // ...existing code... addEventListener(this); } // ...existing code... public void eventNotifyReceived(String uuid, long seq, String name, String value) { // ...existing code... } } ``` -------------------------------- ### Check Specific File Javadoc Warnings Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/JAVADOC_STATUS.md This command filters Javadoc warnings to show only those related to a specific file. Use this to pinpoint issues in a particular Java class. ```bash mvn -q javadoc:javadoc 2>&1 | grep "ClassName.java" ``` -------------------------------- ### HTTPRequestListener Interface Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Defines the interface for handling HTTP requests received by a UPnP device. Implement this to process incoming requests. ```java public interface HTTPRequestListener { public void httpRequestReceived(HTTPRequest httpReq); } ``` -------------------------------- ### Action Class Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/docs/STYLEGUIDE_JAVADOC.md The Action class represents a UPnP action that can be invoked on a service. It provides methods to interact with UPnP services remotely. ```APIDOC ## Action ### Description Represents a UPnP action that can be invoked on a service. Actions are methods exposed by UPnP services that can be called remotely by control points. Each action has a name, a list of input arguments, and a list of output arguments. This class is thread-safe. ### Example Usage ```java Action action = service.getAction("SetVolume"); action.setArgumentValue("DesiredVolume", 50); action.postControlAction(); ``` ### See Also - Service - Argument ### Since 2.1.5 ``` -------------------------------- ### Set IPv6 Site Local Scope Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Change the default link-local scope for IPv6 multicasting to site-local scope. This affects how UPnP discovery and communication occur over IPv6 networks. ```java UPnP.setEnable(UPnP.USE_IPV6_SITE_LOCAL_SCOPE); ``` -------------------------------- ### Subscribe to Service Events Source: https://context7.com/cybergarage/cybergarage-upnp/llms.txt Registers for state change notifications from a UPnP service. The ControlPoint must implement the EventListener interface to receive notifications. Subscriptions are automatically renewed if NMPR mode is enabled. ```java import org.cybergarage.upnp.*; import org.cybergarage.upnp.event.EventListener; public class MyControlPoint extends ControlPoint implements EventListener { public MyControlPoint() { addEventListener(this); // register for all incoming event notifications } // Called whenever a subscribed state variable changes value @Override public void eventNotifyReceived(String uuid, long seq, String varName, String value) { System.out.printf("Event [sid=%s seq=%d] %s = %s%n", uuid, seq, varName, value); } public void run() throws Exception { start(); Thread.sleep(3000); Device clockDev = getDevice("My Clock"); if (clockDev == null) { stop(); return; } Service timerSvc = clockDev.getService("urn:schemas-upnp-org:service:timer:1"); boolean subscribed = subscribe(timerSvc); // infinite timeout subscription if (subscribed) { System.out.println("Subscribed, SID=" + timerSvc.getSID() + " timeout=" + timerSvc.getTimeout()); } Thread.sleep(30_000); // receive events for 30 seconds unsubscribe(timerSvc); // explicit unsubscribe (also called by stop()) stop(); } public static void main(String[] args) throws Exception { new MyControlPoint().run(); } } ``` -------------------------------- ### Post Query Control Request Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Send a query control message to retrieve the current value of a state variable. Handles potential errors during the query. ```java Device clockDev = ...; StateVariable timeStateVar = clockDev.getStateVariable("time"); if (timeStateVar.postQueryControl()) { String value = timeStateVar.getValue(); // ...existing code... } else { UPnPStatus err = timeStateVar.getUPnPStatus(); System.out.println("Error Code = " + err.getCode()); System.out.println("Error Desc = " + err.getDescription()); } ``` -------------------------------- ### Send UPnP State Variable Updates for Eventing Source: https://github.com/cybergarage/cybergarage-upnp/blob/master/doc/cybergarage-upnp-prgguide.md Update a state variable using ServiceStateVariable::setValue() to automatically send the new state to subscribed control points. This is the primary mechanism for device event notifications. ```java Device clockDevice = ...; StateVariable timeVar = clockDevice.getStateVariable("Time"); String timeStr = ...; timeVar.setValue(timeStr); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.