[JAVA] Registrieren Sie DLNA-kompatibles Fernsehgerät in SORACOM Inventory und arbeiten Sie über die Webkonsole

Einführung

Dies ist Yasukawa aus Soracom. SORACOM-Inventar als öffentliche Beta veröffentlicht im SORACOM Technology Camp im April / 04/26 / inventar-public-release /) Habt ihr es versucht?

Wie Sie im verlinkten Blog sehen können, haben wir es bei der Erstellung der öffentlichen Beta in Form des Hinzufügens neuer Funktionen veröffentlicht, basierend auf dem Feedback von Kunden, die es mit der privaten Beta und der eingeschränkten Vorschau ausprobiert haben, aber eine der neuen Funktionen Zum einen werden benutzerdefinierte Modelle unterstützt. Dieses Mal möchte ich diese Funktion nutzen, um einen Deep Dive zu machen.

In SORACOM Inventory folgen der auf dem Gerät ausgeführte Agent und der Server auf der SORACOM-Seite dem standardisierten Geräteverwaltungsprotokoll OMA DM LwM2M. Kommunizieren. Zu Beginn der Version wurde nur Standardobjektdefinition unterstützt, daher Allzweckgeräte wie Temperatursensoren und Beschleunigungssensoren Obwohl es möglich war, gemäß der vorhandenen Definition zu implementieren, gab es ein Problem, dass es im Inventar nicht gut ausgedrückt werden konnte, wenn versucht wurde, Geräte zu verbinden, die nicht dem Standard entsprechen.

Wie der Name schon sagt, können Sie mit der diesmal veröffentlichten Unterstützung für benutzerdefinierte Modelle eine beliebige Objektmodelldefinition registrieren und zur Nachrichteninterpretation verwenden, wenn Server und Gerät in SORACOM Inventory interagieren, oder zur Anzeige auf der Webkonsole. Es ist eine Funktion, die ausgeführt werden kann. Mit anderen Worten, wenn Sie diese Funktion verwenden, können Sie Ihre eigenen Definitionen registrieren und im Inventar verwalten, auch wenn die Gerätetypen und -spezifikationen nicht im Standard definiert sind.

Es war eine lange Einführung, aber ich wollte es schon immer machen, seit ich diese Funktion entwickelt habe, und ich wollte immer einen Artikel schreiben, der es tatsächlich versucht hat. Wie der Titel schon sagt, geht es darum, den Fernseher mit SORACOM Inventory vor Ihnen zu bedienen!

(Dieser Blog soll übrigens ein Artikel sein, den ich bei Deep Dive ausprobiert habe, daher bin ich kurz vor dem Abgabetermin, möchte mich aber für [Try SORACOM Challenge Campaign] bewerben (https://pages.soracom.jp/20180426-0630_IoT_DIY_campaign.html). Ich denke. "Ziel: Jeder, unabhängig von Unternehmen oder Einzelperson, kann teilnehmen." Da es geschrieben wurde, hoffe ich, dass es eine coole Neuheit wird.)

Betreiben Sie ein DLNA-kompatibles Fernsehgerät

Heutzutage unterstützen die meisten Heimfernseher DLNA und sind über Ethernet oder WiFi mit ihrem Heimnetzwerk verbunden. Ich bin sicher, dass Ihr Fernseher zu Hause auch regelmäßig über DLNA mit anderen Geräten kommuniziert. Wenn Sie eine solche Umgebung vor sich haben, können Sie tatsächlich versuchen, was in diesem Blog geschrieben steht.

Insbesondere geht es darum, ein DLNA-kompatibles Fernsehgerät mit UPnP zu entdecken, eine Verbindung zum OMA DM LwM2M-Protokoll SORACOM Inventory herzustellen und es über die Inventory-Webkonsole zu bedienen. (Entschuldigen Sie diejenigen, die gegen die Abkürzung des Alphabets allergisch sind. Ich denke, dass es eine Ablehnungsreaktion gibt, aber vorerst ist es in Ordnung, wenn Sie glauben, dass Sie den Fernseher in einem Chaos betreiben.)

Zum Zeitpunkt des Adventskalenders 2015 schrieb ich einen Blog mit dem Titel Discover Thing and Beam, entdeckte aber zu diesem Zeitpunkt einen DLNA-kompatiblen Fernseher mit UPnP. Dann ging es darum, AWS IoT bei Beam MQTT zu registrieren und zu betreiben. Es ist leicht zu verstehen, wenn Sie glauben, dass MQTT, AWS IoT durch LwM2M, SORACOM Inventory ersetzt wurde (leicht zu verstehen, nicht wahr?).

Zu dieser Zeit habe ich übrigens so etwas wie einen UPnP <-> MQTT-Agenten mit node.js erstellt, aber im Fall von SORACOM Inventory ist die Agentenkonstruktion aus der benutzerdefinierten Modelldefinition sehr reibungslos, wenn Sie die Java-Client-Bibliothek verwenden, diesmal also mit Java Ich würde gerne gehen.

Wie beim vorherigen Blog-Schreiben möchte ich diese Zeit implementieren und mich auf Anwendungsfälle wie Videowiedergabe, Lautstärke erhöhen / verringern und Erkennung des Ein- und Ausschaltens des Fernsehgeräts konzentrieren.

Ich habe ein Video der tatsächlichen Bewegung aufgenommen. Bitte schauen Sie hier, um eine Vorstellung davon zu bekommen, was sie tut. Ich hoffe, Sie verstehen, dass das Verfahren zur Implementierung später beschrieben wird.

Steuern Sie DLNA TV mit SORACOM Inventory

Ich werde es tatsächlich schaffen

Als SDK für SORACOM Inventory ist die Java-Client-Bibliothek von @ c9katayama für die Öffentlichkeit zugänglich, und die Readme-Datei enthält Detaillierte Implementierungsverfahren für Agenten. /blob/master/README_ja.md) ist so geschrieben, dass es reibungslos verläuft, wenn Sie fortfahren, während Sie dies betrachten.

Insbesondere definieren wir ein benutzerdefiniertes Modell für DLNA TV, generieren Java-Code aus der Definitionsdatei und füllen ihn aus.

1. Erstellen Sie eine benutzerdefinierte Modelldefinition

Die Modelldefinition unterstützt sowohl XML als auch JSON. Dieses Mal habe ich das Beispiel in der Readme-Datei der Java-Client-Bibliothek kopiert und bearbeitet, sodass es sich um XML handelt. Um diesen Anwendungsfall zu implementieren, verwenden Sie UPnPs Rendering Control Service und [AV Transport Service](http: / /www.upnp.org/specs/av/UPnP-av-AVTransport-v3-Service-20101231.pdf) ist erforderlich, daher definieren wir Aktionsparameter und Aktionen unter Bezugnahme auf jede Spezifikation.

Ich war besorgt über den Wert der ID, die jeder Ressource zugeordnet ist, entschied mich jedoch vorerst für eine sehr grobe Option, die Abschnittsnummer für die Spezifikation der einzelnen Parameter und Aktionen zu verwenden.

Ich werde die Definition von Parametern und Aktion so schreiben.

resource-example.xml


  <Item ID="2216">
    <Name>Volume</Name>
    <Operations>R</Operations>
    <MultipleInstances>Single</MultipleInstances>
    <Mandatory>Mandatory</Mandatory>
    <Type>Integer</Type>
    <RangeEnumeration />
    <Units></Units>
    <Description>Current audio volume of the renderer</Description>
  </Item>

(Ich bin es leid, alles zu versuchen, also habe ich mich auf die Anwendungsfälle konzentriert, die ich implementieren wollte.)

Hier ist die fertige Objektdefinitionsdatei:

Wenn Sie dies als benutzerdefiniertes Modell registrieren, sind die Vorbereitungen auf der Seite des SORACOM-Inventars abgeschlossen. Wenn das Gerät danach online geschaltet wird, wird das entsprechende Element automatisch auf der Konsole angezeigt.

image.png

Ausführliche Informationen zur Definition des benutzerdefinierten Objektmodells finden Sie unter hier.

2. Generieren Sie Java-Code aus der Objektdefinitionsdatei und implementieren Sie die Methode

Die Inventory-Clientbibliothek ist großartig, da sie auch die Generierung von Klassendateien aus Objektdefinitionen unterstützt. Verwenden wir also diese Funktion.

Hier ist der Quellgenerator-Code, der geringfügig geändert wurde, um eine Klassendatei aus der im vorherigen Abschnitt erstellten Datei zu generieren. Er bezieht sich auf den Beispielcode auf Github.

JavaSourceGenerator.java


package models;

import io.soracom.inventory.agent.core.util.TypedAnnotatedObjectTemplateClassGenerator;

import java.io.File;

public class JavaSourceGenerator {

    public static void main(String[] args) {
        String javaPackage = "models";
        File sourceFileDir = new File("src/main/java");
        TypedAnnotatedObjectTemplateClassGenerator generator = new TypedAnnotatedObjectTemplateClassGenerator(
                javaPackage, sourceFileDir);
        File[] modelFiles = new File("src/main/resources").listFiles();
        for (File modelFile : modelFiles) {
            generator.generateTemplateClassFromObjectModel(modelFile);
        }
        System.out.println("Finished generating Java source.");
        System.exit(0);
    }
}

Dadurch wird eine Klasse generiert, die dem Paket models entspricht.

Wenn man den Inhalt betrachtet, sieht es so aus.

UPnPRenderingControlServiceObject.java


package models;
import io.soracom.inventory.agent.core.lwm2m.*;
import java.util.Date;
import org.eclipse.leshan.core.node.ObjectLink;

/**
 * LwM2M device object model for UPnP Rendering Control service.
 **/
@LWM2MObject(objectId = 30001, name = "UPnP Rendering Control Service", multiple = true)
public class UPnPRenderingControlServiceObject extends AnnotatedLwM2mInstanceEnabler {

	/**
	 * Mute status of the renderer
	 **/
	@Resource(resourceId = 2215, operation = Operation.Read)
	public Boolean readMute()	{
		throw LwM2mInstanceResponseException.notFound();
	}

	/**
	 * Current audio volume of the renderer
	 **/
	@Resource(resourceId = 2216, operation = Operation.Read)
	public Integer readVolume()	{
		throw LwM2mInstanceResponseException.notFound();
	}

	/**
	 * Sets the renderer audio volume.
	 **/
	@Resource(resourceId = 2430, operation = Operation.Execute)
	public void executeSetVolume(String executeParameter)	{
		throw LwM2mInstanceResponseException.notFound();
	}
}

Danach können Sie es so implementieren, dass es die jeder Methode entsprechende UPnP-Aktion aufruft. Es fühlt sich an, als würde es den Fluss entlang gehen, also ist es schön zu wissen, was zu tun ist!

3. Implementieren Sie jede Methode, die der LwM2M-Ressource entspricht

Dieses Mal zielen wir auf UPnP-Geräte ab. Als nächstes werden wir es mithilfe der UPnP-Bibliothek implementieren. Ich habe mich für cling library entschieden, weil es einfach zu bedienen zu sein schien.

Fügen Sie build.gradle Folgendes hinzu und Sie können loslegen.

build.gradle


apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'application'

repositories {
  mavenCentral()
  maven { url 'https://soracom.github.io/maven-repository/' }
  maven { url 'http://4thline.org/m2/' } // <-hinzufügen
}

def INVENTORY_AGENT_VERSION="0.0.5"

dependencies {
    compile "io.soracom:soracom-inventory-agent-for-java-core:$INVENTORY_AGENT_VERSION"
    compile "org.fourthline.cling:cling-core:2.1.1" // <-hinzufügen
    testCompile 'junit:junit:4.12'
}

jar {
    manifest {
        attributes "Main-Class": "App"
    }
}


mainClassName = 'App'

Bei einigen der implementierten UpnpRenderingControlServiceObject-Methoden sieht es so aus.

UpnpRenderingControlServiceObject.java


    /**
     * Current audio volume of the renderer
     **/
    @Resource(resourceId = 2216, operation = Operation.Read)
    public Long readVolume()	{
        ActionInvocation actionInvocation =
                new ActionInvocation(renderingControlService.getAction(ACTION_GET_VOLUME));
        actionInvocation.setInput(ARG_INSTANCE_ID, new UnsignedIntegerFourBytes(0));
        actionInvocation.setInput(ARG_CHANNEL, VALUE_CHANNEL_MASTER);
        Map<String, ActionArgumentValue> output = UpnpController.getInstance().executeUpnpAction(actionInvocation);
        return ((UnsignedIntegerTwoBytes)output.get(ARG_CURRENT_VOLUME).getValue()).getValue();
    }

    /**
     * Sets the renderer audio volume.
     **/
    @Resource(resourceId = 2430, operation = Operation.Execute)
    public void executeSetVolume(String executeParameter)	{

        ActionInvocation setVolumeInvocation =
                new ActionInvocation(renderingControlService.getAction(ACTION_SET_VOLUME));
        setVolumeInvocation.setInput(ARG_INSTANCE_ID, new UnsignedIntegerFourBytes(0));
        setVolumeInvocation.setInput(ARG_CHANNEL, VALUE_CHANNEL_MASTER);
        setVolumeInvocation.setInput(ARG_DESIRED_VOLUME, new UnsignedIntegerTwoBytes(executeParameter));
        UpnpController.getInstance().executeUpnpAction(setVolumeInvocation);
    }

Kurz gesagt, es fühlt sich an, als würde die von LwM2M empfangene Anforderung in die entsprechende Aktion von UPnP konvertiert. Beide Protokolle haben ähnliche Konzepte zum Ausdrücken des Geräts, die die Grundlage bilden, sodass die Konvertierung relativ einfach war.

Hier sind die beiden Dateien, die implementiert wurden:

Wenn Sie einen Agenten erstellen, der diese beiden Objekte (und das grundlegende Geräteobjekt) implementiert, können Sie ihn im Inventar registrieren und mit der API und der Benutzerkonsole betreiben.

Diesmal habe ich es mit dem Namen "MediaRendererAgent" geschafft. Wenn Sie ein UPnP-Gerät finden, erstellen Sie eine separate Klasse mit dem Namen "UpnpDeviceAgent", die dem Geräteobjekt von LwM2M als Basisklasse entspricht. MediaRendererAgent erbt es und erstellt die beiden diesmal definierten Objekte. Es ist gemacht, um hinzugefügt zu werden.

MediaRendererAgent.java


package org.yasukawa.inventory.upnp.media_renderer;

import org.fourthline.cling.model.meta.RemoteDevice;
import org.fourthline.cling.model.meta.Service;
import org.fourthline.cling.model.types.ServiceType;
import org.yasukawa.inventory.upnp.UpnpDeviceAgent;

public class MediaRendererAgent extends UpnpDeviceAgent {
    public static final String MEDIA_RENDERER_DEVICE_TYPE = "urn:schemas-upnp-org:device:MediaRenderer:1";
    public static final String RENDERING_CONTROL_SERVICE_TYPE = "urn:schemas-upnp-org:service:RenderingControl:1";
    public static final String AV_TRANSPORT_SERVICE_TYPE = "urn:schemas-upnp-org:service:AVTransport:1";
    public static final String ATTR_LAST_CHANGE = "LastChange";
    public static final String ATTR_INSTANCE_ID = "InstanceID";

    public MediaRendererAgent(RemoteDevice device){
        super(device);
        for ( Service service : device.getServices()){
            System.out.println(service.getServiceType());
            System.out.println(service.getServiceId());
        }
        super.initializer.addInstancesForObject(new UpnpRenderingControlServiceObject(
                device.findService(ServiceType.valueOf(RENDERING_CONTROL_SERVICE_TYPE)))
        );
        super.initializer.addInstancesForObject(new UpnpAvTransportServiceObject(
                device.findService(ServiceType.valueOf(AV_TRANSPORT_SERVICE_TYPE)))
        );
    }
}

4. Nachdem Sie das UPnP-Gerät erkannt haben, erstellen Sie einen Inventaragenten und registrieren Sie ihn.

Wenn Sie dies bisher tun können, entdecken Sie das UPnP-Gerät. Wenn Sie einen Media Renderer wie einen Fernseher finden, erstellen Sie eine Instanz des Media Renderer-Agenten und registrieren Sie ihn. Sie können den Fernseher dann mit der Inventar-API betreiben! heiß!

Wenn cling dieses Mal verwendet wird, wenn Sie Discovery starten, nachdem Sie eine Instanz einer Klasse registriert haben, die eine Schnittstelle namens "UpnpRegistryListener" im UPnP-Kontrollpunkt implementiert, Es wurde so konzipiert, dass Sie jedes Mal zurückrufen können, wenn Sie ein Gerät finden. Wenn nach dem Empfang dieses Rückrufs das gefundene Gerät Media Renderer ist, scheint es, als würde man eine Logik schreiben, um eine Instanz von Media Renderer Agent zu erstellen und zu starten. Im Einzelnen sieht es wie folgt aus.

InventoryUpnpRegistryListener.java


    @Override
    public void remoteDeviceAdded(Registry registry, RemoteDevice device) {
        logger.info("Device {} with type {} is added", device.getIdentity().toString(), device.getType().toString());
        if (MediaRendererAgent.MEDIA_RENDERER_DEVICE_TYPE.equals(device.getType().toString())){
            logger.info("Media renderer found: " + device.getDetails().getFriendlyName());
            MediaRendererAgent agent = new MediaRendererAgent(device);
            logger.info("Starting agent for {} and registering to SORACOM Inventory",
                    device.getIdentity().toString());
            agent.start();
            agentMap.put(device.getIdentity().toString(), agent);
        }
    }

    @Override
    public void remoteDeviceRemoved(Registry registry, RemoteDevice device) {
        logger.info("Device {} with type {} is removed", device.getIdentity().toString(), device.getType().toString());
        if (agentMap.containsKey(device.getIdentity().toString())){
            logger.info("Stopping agent for {} and deregistering from SORACOM Inventory",
                    device.getIdentity().toString());
            agentMap.remove(device.getIdentity().toString()).stop();
        }
    }

Übrigens werde ich den Agenten stoppen, wenn das Ereignis eintritt, dass das Gerät gelöscht wird. Wenn Sie auf diese Weise die Stromversorgung des Fernsehgeräts ausschalten, kann sogar das Inventar auf Offline verschoben werden.

Registrieren Sie abschließend diesen "UpnpRegistryListener" im UPnP Control Point in der Haupt-App.java und starten Sie Discovery, und Sie sind fertig!

App.java


import org.fourthline.cling.UpnpService;
import org.fourthline.cling.UpnpServiceImpl;
import org.fourthline.cling.model.message.header.STAllHeader;
import org.yasukawa.inventory.upnp.InventoryUpnpRegistryListener;
import org.yasukawa.inventory.upnp.UpnpController;

public class App {

	public static void main(String[] args) throws Exception {

		UpnpService upnpService = new UpnpServiceImpl();
		UpnpController.initialize(upnpService);
		upnpService.getRegistry().addListener(new InventoryUpnpRegistryListener(upnpService));
		upnpService.getControlPoint().search(new STAllHeader());
	}
}

Ich werde es tatsächlich bewegen

Der diesmal erstellte Code befindet sich in diesem Repository. Sie können ein Zip-Archiv für die Verteilung erstellen, indem Sie die folgenden Schritte ausführen.

$ git clone https://github.com/kntyskw/inventory-upnp
$ cd inventory-upnp
$ gradle distZip

Kopieren Sie das damit erstellte . / Build / Distributions / Inventar-upnp.zip in einen Raspeltorte usw., der sowohl mit Ihrem Heim-LAN als auch mit SORACOM Air verbunden ist, und entpacken Sie es, und Sie können es ausführen (vorausgesetzt, JRE ist vorhanden). ..

image.png

Stellen Sie dieses Archiv anschließend auf einem Gerät bereit, das als UPnP-Gateway wie Raspeye ausgeführt wird, und führen Sie es aus.

Nebenbei habe ich kürzlich resin.io verwendet, mit dem Sie Docker-Container auf IoT-Geräten bereitstellen können, um auf einfache Weise Software auf Raspai bereitzustellen. Weitere Informationen finden Sie auf der Website der Head-Familie. Wenn Sie jedoch die Umgebung von resin.io bereits eingerichtet haben, können Sie den aktualisierten Container wie folgt für Raspai bereitstellen.

$ git add inventory-upnp.zip
$ git commit -m "add/update inventory-upnp.zip"
$ git push resin master

Darüber hinaus können Sie von der Webkonsole von resin.io aus SSH an Raspeye senden und Container nach Belieben neu starten und aktualisieren. Bitte versuchen Sie es, wenn Sie möchten.

Führen Sie nach dem Bereitstellen und Extrahieren des Archivs unabhängig von der Prozedur den folgenden Befehl im Zielverzeichnis aus.

$ ./bin/inventory-upnp

Dann fungiert Raspai als UPnP-Gateway. Wenn ein DLNA-kompatibles Fernsehgerät gefunden wird, wird es im SORACOM-Inventar registriert und betriebsbereit gemacht! Ab diesem Zeitpunkt können Sie wie im Video zu Beginn gezeigt arbeiten.

image.png

abschließend

Was haben Sie gedacht? Das Konzept des Umgangs mit UPnP- und LwM2M-Geräten (genauer gesagt OMA DM) ist grundsätzlich ähnlich, sodass wir UPnP-Geräte problemlos im SORACOM-Inventar registrieren konnten.

Dieses Mal haben wir uns mit UPnP befasst. Wenn das Protokoll jedoch über einen Mechanismus wie Ermittlung, Befehlsausführung und Abonnieren von Ereignissen verfügt, können Sie den Inventaragenten implementieren und in SORACOM Inventory verfügbar machen. Wenn Sie beispielsweise Bonjour für Apple TV verwenden, können Sie dasselbe tun.

Wenn Sie also SORACOM Air SIM und Inventory Agent auf einem Gerät ausführen, das ein Protokoll-Gateway sein wird, können Sie alle umgebenden Geräte über Inventory verwalten. (Und mit der Kombination von SORACOM Air + Inventory erfolgt die automatische Weitergabe von Authentifizierungsinformationen an das Protokoll-Gateway ebenfalls automatisch!) Warum registrieren Sie Ihre Heimgeräte nicht in SORACOM Inventory, damit Sie sie von überall aus überwachen und steuern können?

Übrigens, wie ich mich erinnerte, als ich Discovery and Event abonniert habe, haben Sie das Event SORACOM Discovery bereits am 4. Juli abonniert? Wenn Sie dies nicht getan haben, nimmt die Anzahl der verbleibenden Plätze ab, aber ich denke, es wird rechtzeitig sein. Bitte bewerben Sie sich über diesen Link! Übrigens wird dieser Link als meine Einführung gekennzeichnet. Bitte dieser Link ky) Bitte. (Hartnäckig w)

Ich warte nur auf einen Flug vom Silicon Valley nach Tokio. Wir freuen uns darauf, dieses Jahr wieder mit Ihnen über verrückte Themen am Veranstaltungsort SORACOM Discovery zu diskutieren, einschließlich UPnP und SORACOM Inventory!

Recommended Posts

Registrieren Sie DLNA-kompatibles Fernsehgerät in SORACOM Inventory und arbeiten Sie über die Webkonsole
21 Lesen Sie das Skript aus der Datei und führen Sie es aus
Stellen Sie die Sensorinformationen von Raspberry Pi in Java grafisch dar und überprüfen Sie sie mit einem Webbrowser